Как получить вывод адресного дезинфицирующего средства при выдаче SIGINT, чтобы остановить цикл
Когда я компилирую эту простую тестовую программу, я получаю отчет об очевидной утечке из обработчика адресов, но когда я компилирую ту же программу, но с бесконечным циклом, и прерываю ее, испуская SIGINT
Я не получаю никакого вывода.
Проверяя вывод asm, malloc
не оптимизирован (если это вообще возможно)
Это ожидаемое поведение адресного дезинфицирующего средства? Я не сталкиваюсь с этой проблемой в других разработках.
Рабочий пример:
#include <stdlib.h>
int main(void)
{
char *a = malloc(1024);
return 1;
}
Не работает (убить с помощью SIGINT):
#include <stdlib.h>
int main(void)
{
char *a = malloc(1024);
for(;;);
return 1;
}
компиляции: gcc test.c -o test -fsanitize=address
Я столкнулся с этой проблемой в полной программе, но я сократил ее до этого минимального примера.
3 ответа
Я пробовал много способов, с exit()
а также abort()
звонки, это работает:
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
jmp_buf jmpbuf;
void handler (int signum) {
printf("handler %d \n", signum);
// we jump from here to main()
// and then call return
longjmp(jmpbuf, 1);
}
int main(int argc, char *argv[])
{
if (setjmp(jmpbuf)) {
// we are in signal context here
return 2;
}
signal(SIGINT, handler);
signal(SIGTERM, handler);
char *a = malloc(1024);
while (argc - 1);
return 1;
}
Результаты в:
> gcc file.c -fsanitize=address && timeout 1 ./a.out arg
handler 15
=================================================================
==12970==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1024 byte(s) in 1 object(s) allocated from:
#0 0x7f4798c9bd99 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
#1 0x5569e64e0acd in main (/tmp/a.out+0xacd)
#2 0x7f479881206a in __libc_start_main (/usr/lib/libc.so.6+0x2306a)
SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 1 allocation(s).
Я предполагаю, что функция дезинфекции адреса выполняется после основного возврата.
Код, отвечающий за вывод этой ошибки, называется деструкторной (конечной) процедурой. Поскольку ваша программа завершает работу без вызова какого-либо деструктора процесса (из-за SIGINT), вы не получите никаких распечаток ошибок.
__lsan_do_leak_check() может помочь вам избежать использования longjmp в ответе @KamilCuk:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sanitizer/lsan_interface.h>
void handler (int signum) {
__lsan_do_leak_check();
}
int main(int argc, char *argv[])
{
signal(SIGINT, handler);
char *a = malloc(1024);
a=0;
printf("lost pointer\n");
for(;;);
return 1;
}
Демо:
clang test.c -fsanitize=address -fno-omit-frame-pointer -g -O0 -o test && ./test
lost pointer
C-c C-c
=================================================================
==29365==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1024 byte(s) in 1 object(s) allocated from:
#0 0x4c9ca3 in malloc (/home/bjacob/test+0x4c9ca3)
#1 0x4f9187 in main /home/bjacob/test.c:13:14
#2 0x7fbc9898409a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)
SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 1 allocation(s).
Обратите внимание, что я добавил a=0, чтобы создать утечку.
Я также добавил файл printf. Без этого printf ошибка утечки не печатается. Я подозреваю, что компилятор оптимизировал использование переменной «a», несмотря на то, что я использовал параметр компилятора -O0.