Почему перехват HeapFree с Detours не работает для удаления/бесплатного?

Я пытаюсь написать трекер памяти для своего приложения Windows. Я уже закончил прототип, используя Detours. Я подключил HeapAlloc, HeapReAlloc, HeapFree, HeapDestroy и вывел несколько журналов для проверки. Однако что-то не так.

Вот мой пример кода:

void thread_foo()
{
    while(1)
    {
        void* tempPtr = HeapAlloc(GetProcessHeap(), 0, 3);
        Sleep(50);
    }
}

int main()
{
    std::thread tobj(thread_foo);
    int size = 16;
    tobj.join();
}

А вот мой результат отслеживания (первые 32 строки, формат ALLOC/FREE/REALLOC/DESTROY: метка времени, хэш стека вызовов, указатель кучи, флаги, размер, указатель результата):

ALLOC:2736795824738, -592122872, 0000019110690000, 0, 256, 000001911069E130
ALLOC:2736795825084, 1232708493, 0000019110690000, 0, 16, 000001911069F0A0
ALLOC:2736795825225, -929256262, 0000019110690000, 0, 56, 000001911069FAF0
ALLOC:2736795825284, -929523462, 0000019110690000, 0, 2, 000001911069FBF0
ALLOC:2736795825323, 151458640, 0000019110690000, 0, 2, 000001911069FBF0
ALLOC:2736795825369, -929340699, 0000019110690000, 0, 16, 000001911069F200
ALLOC:2736795825404, 1203567881, 0000019110690000, 0, 48, 000001911069F570
ALLOC:2736795825436, 1789431341, 0000019110690000, 8, 344, 000001911069FC10
ALLOC:2736795825511, -1394565794, 0000019110690000, 0, 1702, 000001911069FD70
ALLOC:2736795825573, 955998638, 0000019110690000, 0, 6, 000001911069E240
ALLOC:2736795825600, -958719147, 0000019110690000, 0, 2, 000001911069E260
ALLOC:2736795825625, 955994058, 0000019110690000, 8, 4, 000001911069E280
ALLOC:2736795825651, 1789431550, 0000019110690000, 8, 344, 000001911069E2A0
ALLOC:2736795825677, -1394565585, 0000019110690000, 0, 1702, 000001911069FD70
ALLOC:2736795825714, 955998680, 0000019110690000, 0, 6, 000001911069E280
ALLOC:2736795825736, 122263169, 0000019110690000, 0, 2, 000001911069E240
ALLOC:2736795825761, 1203256005, 0000019110690000, 8, 512, 000001911069E400
ALLOC:2736795825786, 955996289, 0000019110690000, 8, 4, 000001911069E610
ALLOC:2736795825810, 1789433781, 0000019110690000, 8, 344, 000001911069FC10
ALLOC:2736795825834, -1394563354, 0000019110690000, 0, 1702, 000001911069FD70
ALLOC:2736795825868, 956000911, 0000019110690000, 0, 6, 000001911069E610
ALLOC:2736795825893, 1203615483, 0000019110690000, 0, 16, 000001911069F140
ALLOC:2736795825921, 1232708730, 0000019110690000, 0, 16, 000001911069F160
ALLOC:2736795825945, -929316070, 0000019110690000, 0, 16, 000001911069F260
ALLOC:2736795825968, 1232708941, 0000019110690000, 0, 16, 000001911069F1A0
ALLOC:2736795825990, -929340251, 0000019110690000, 0, 16, 000001911069F2A0
ALLOC:2736795826013, 1232709165, 0000019110690000, 0, 16, 000001911069F0C0
ALLOC:2736795826033, -929340027, 0000019110690000, 0, 16, 000001911069F100
ALLOC:2736795826066, 151797360, 0000019110690000, 0, 16, 000001911069F120
ALLOC:2736795826106, -929229531, 0000019110690000, 0, 16, 000001911069F2C0
ALLOC:2736795826131, 1203787877, 0000019110690000, 0, 96, 000001911069E240
ALLOC:2736795826158, 1789651341, 0000019110690000, 8, 344, 000001911069FD70

Проблема в том, что 4-я и 5-я строки, как мы видим, получают один и тот же указатель. Между ними нет HeapFree или HeapDestroy. И эти 2 HeapAllocs не мои вызовы, могу определить по размеру. Я предполагаю, что они связаны с std::thread. И они не единственная такая же пара. 9-я, 14-я, 20-я, 32-я строки тоже одинаковые.

Если удалить связанные с потоком коды, просто вызвав thread_foo() в main(), все снова будет выглядеть хорошо.

Кто-нибудь понимает это?

PS Если кого-то интересует код перехвата, он просто основан на https://github.com/microsoft/Detours/blob/master/samples/tracemem/trcmem.cpp

Я добавил перехват HeapReAlloc, HeapFree, HeapDestroy и сбор логов в файл.

ВСЕ ЧИСТО! ВСЁ ЧИСТО!

Я нашел почему. Причина в том, что хотя я перехватил HeapFree, вся память, освобожденная с помощью delete или free(), не вызвала мой обернутый HeapFree. Не знаю почему, но это факт. Теперь я также подключил CRT free(), появляется ранее скрытое бесплатное сообщение.

Поэтому я изменил название этого вопроса. Надеялся, что у кого-нибудь есть хоть малейшее представление об этом.


person Zimian    schedule 03.01.2020    source источник
comment
Я не знаю библиотеку обходов, но одна из возможных проблем с вашим кодом заключается в том, что join() никогда не вернется, поэтому остальную часть кода в main() должен удалить любой приличный оптимизатор.   -  person Ted Lyngmo    schedule 03.01.2020
comment
@TedLyngmo спасибо, в этой части вы правы. Я уберу эти коды, чтобы избежать двусмысленности.   -  person Zimian    schedule 03.01.2020
comment
Нам нужно увидеть код вашего хука. Скорее всего, с ним что-то не так. Например, это потокобезопасно?   -  person Paul Sanders    schedule 03.01.2020
comment
@PaulSanders В Detours 4.0.1 есть образец под названием tracemem, мой код перехвата основан на нем, я думаю, ничего особенного.   -  person Zimian    schedule 06.01.2020


Ответы (1)


Почти каждая современная реализация C++ будет перерабатывать небольшие аллокации внутри себя, без участия ОС. Задействование ОС требует определенных затрат времени, и несколько сэкономленных байтов просто не оправдывают этого.

person MSalters    schedule 07.01.2020