我正在用 C++ 编写一个调试器,退出时我需要它来清除调试对象中设置的所有断点。
我创建了一个名为 BREAKPOINT_INFO
的 struct
,其中包含清理每个断点所需的信息。诸如进程句柄 (hProcess
)、断点的虚拟内存地址 (lpBreakPoint
) 以及被替换的原始指令的操作码 ( >指令
)。
然后,我有一个 CleanUp
成员函数,它使用上述数据成员来恢复原始指令,以便调试对象不会崩溃。
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;
但是,当我尝试为每个 BREAKPOINT_INFO
结构传递成员函数时,我收到编译错误:
C:\...\...\main.cpp|39|错误:无法将“BREAKPOINT_INFO::CleanUp”从类型“void (BREAKPOINT_INFO::)()”转换为类型“void ( __attribute__((__cdecl__)) *)()'|
即使在尝试转换为该类型之后,它也无法编译。是否可以将成员函数传递给atexit?如果是这样,我将如何去做呢?感谢您抽出时间。
最佳答案
不,除了函数指针之外,您不能将任何东西传递给 atexit
,如其声明所指定的。
int atexit (void (*func)(void)) noexcept
成员函数不是免费函数。
正如您在错误消息中看到的,它的类型 void (BREAKPOINT_INFO::)()
与 void ()
不相同.
事实上,指向成员函数的指针需要一个额外的第一个参数来指定类的哪个实例正在调用成员函数。
auto member_function_pointer = BREAKPOINT_INFO::CleanUp;
BREAKPOINT_INFO some_info;
member_function_pointer(&some_info); //is equivalent to...
some_info.CleanUp();
不,您不能将捕获 lambda 作为函数指针传递。非捕获 lambda 具有 public non-virtual non-explicit const conversion function to pointer to function ,这可能是函数指针可以指向其他事物的误解的根源。
正如评论中提到的,您应该做的是使用析构函数来进行清理工作。此模式称为 RAII ,并且是迄今为止最好的之一。
作为旁注,您不需要在 C++ 中的 struct
声明上执行疯狂的 typedef
,您所编写的内容看起来很像带有方法的 C。
关于c++ - 尝试将结构成员函数传递给 atexit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43690677/