I am writing a debugger in C++ and upon exit I need it to cleanup any breakpoints set in the debuggee.
I have made a struct
called BREAKPOINT_INFO
that contains the information needed to cleanup each breakpoint. Information such as a handle to the process(hProcess
), the virtual memory address of the breakpoint(lpBreakPoint
), and the opcode of the original instruction that was replaced(instr
).
I then have a CleanUp
member function that uses the data members described above to restore the original instruction so the debuggee doesn't crash.
typedef struct
{
HANDLE hProcess;
PCHAR lpBreakPoint;
CHAR instr;
void CleanUp()
{
DWORD dwError = 0;
std::ostringstream oss;
LPSTR szErrorRest = (LPSTR)"Error restoring original instruction: ";
if(!WriteProcessMemory(hProcess, lpBreakPoint, &instr, sizeof(CHAR), NULL))
{
dwError = GetLastError();
oss << szErrorRest << dwError;
szErrorRest = oss.str().c_str();
MessageBox(NULL, szErrorRest, "ERROR", MB_OK|MB_ICONERROR);
}
}
}BREAKPOINT_INFO, *PBREAKPOINT_INFO;
However, when I try to pass my member function for each BREAKPOINT_INFO
structure, I get a compilation error:
C:\...\...\main.cpp|39|error: cannot convert 'BREAKPOINT_INFO::CleanUp' from type 'void (BREAKPOINT_INFO::)()' to type 'void (__attribute__((__cdecl__)) *)()'|
And even after trying to cast to that type it fails to compile. Is it possible to pass a member function to atexit
? And if so, how would I go about doing so? Thank you for your time.
No you cannot pass anything other than a function pointer to atexit
, as specified by its declaration.
int atexit (void (*func)(void)) noexcept
A member function is not a free function.
As you can see in your error message, it has type void (BREAKPOINT_INFO::)()
which is not the same as void ()
.
A pointer to member function in fact, takes an extra first parameter to specify which instance of the class is invoking the member function.
auto member_function_pointer = BREAKPOINT_INFO::CleanUp;
BREAKPOINT_INFO some_info;
member_function_pointer(&some_info); //is equivalent to...
some_info.CleanUp();
And no, you cannot pass a capturing lambda as a function pointer. A non capturing lambda has an public non-virtual non-explicit const conversion function to pointer to function, which may be the source of misconception that a function pointer can point to other things.
What you should do instead, as mentioned in the comments, is to use a destructor to do cleanup work. This pattern is known as RAII, and is by far one of the best.
As a sidenote, you don't need to do crazy typedef
on struct
declarations in C++, what you are writing looks a lot like C with methods.