Как получить вывод адресного дезинфицирующего средства при выдаче 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.

Другие вопросы по тегам