Я пишу отладчик на C ++, и при выходе он мне нужен для очистки любых точек останова, установленных в отладчике.
Я сделал struct
называется BREAKPOINT_INFO
которая содержит информацию, необходимую для очистки каждой точки останова. Информация, такая как дескриптор процесса (hProcess
) адрес виртуальной памяти точки останова (lpBreakPoint
) и код операции оригинальной инструкции, которая была заменена (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__)) *)()'|
И даже после попытки привести к этому типу он не может скомпилироваться. Можно ли передать функцию-член 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();
И нет, ты не могу передать захват лямбда в качестве указателя на функцию. Не захватив лямбда имеет общедоступная не виртуальная неявная функция преобразования констант в указатель на функцию, что может быть источником неправильного представления о том, что указатель на функцию может указывать на другие вещи.
Вместо этого, как уже упоминалось в комментариях, вы должны использовать деструктор для очистки. Эта модель известна как RAII, и, безусловно, один из лучших.
Как знак, тебе не нужно сводить с ума typedef
на struct
объявления в C ++, то, что вы пишете, очень похоже на C с методами.
Изначально я не собирался писать ответ, поскольку, хотя он и будет правильным и правдивым, он будет приглашать — голосовать, но, тем не менее, это так.
Вы наверняка МОЖЕТЕ передать захватывающий лямбда-объект atexit()
, если ты cify это во-первых, вот пример:
int a = 10;
std::atexit(cify<void(*)()>([a](){std::cout << a << std::endl;}));
но, чтобы решить вашу проблему, я бы предпочел использовать выход из области схема.
Если вы захватите указатель или ссылку на экземпляр какого-либо класса, вы сможете получить доступ к его членам.