我正在用C ++编写调试器,退出后我需要它来清理调试对象中设置的任何断点。
我创建了一个名为struct
的{{1}},其中包含清理每个断点所需的信息。诸如进程句柄(BREAKPOINT_INFO
),断点的虚拟内存地址(hProcess
)以及替换的原始指令的操作码(lpBreakPoint
)之类的信息。 / p>
然后我有一个instr
成员函数,它使用上面描述的数据成员来恢复原始指令,以便调试对象不会崩溃。
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|error: cannot convert 'BREAKPOINT_INFO::CleanUp' from type 'void (BREAKPOINT_INFO::)()' to type 'void (__attribute__((__cdecl__)) *)()'|
?如果是这样,我将如何这样做?谢谢你的时间。
答案 0 :(得分:2)
除了声明指定的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();
相同。
实际上,指向成员函数的指针需要额外的第一个参数来指定该类的哪个实例正在调用成员函数。
typedef
不,你不能将捕获lambda作为函数指针传递。非捕获lambda具有public non-virtual non-explicit const conversion function to pointer to function,这可能是函数指针指向其他事物的误解的来源。
如评论中所提到的,你应该做的是使用析构函数来进行清理工作。这种模式称为RAII,是迄今为止最好的模式之一。
作为旁注,你不需要在C ++的struct
声明中做出疯狂的orderByRaw
,你所写的内容看起来很像C和方法。
答案 1 :(得分:1)
我原本打算写一个答案,因为即使这是正确和真实的,它也会邀请 - 投票,但不过,这里就是这样。
你当然可以将捕获lambda对象传递给atexit()
,如果你先cify,这里是example:
int a = 10;
std::atexit(cify<void(*)()>([a](){std::cout << a << std::endl;}));
但是,为了解决您的问题,我宁愿使用某种scope exit方案。
如果捕获某个类的实例的指针或引用,则可以访问其成员。