Как аннотировать собранный BoehmGC код для Splint? - PullRequest
3 голосов
/ 01 августа 2011

Splint хорошо отслеживает утечки памяти в C-коде.Каждый malloc() должен иметь соответствующий free().Но собранный BoehmGC код использует GC_MALLOC() без соответствия GC_FREE().Это сводит Splint с ума от множества сообщений об утечках памяти, которых на самом деле нет.

Кто-нибудь знает правильную аннотацию для такого кода, чтобы Splint больше не отображал ложные сообщения об утечке памяти?* В частности, кто-то может аннотировать Пример Википедии BoehmGC?

#include <assert.h>
#include <stdio.h>
#include <gc.h>

int main(void)
{
    int i;

    GC_INIT();
    for (i = 0; i < 10000000; ++i)
    {
        int **p = GC_MALLOC(sizeof(int *));
        int *q = GC_MALLOC_ATOMIC(sizeof(int));

        assert(*p == 0);
        *p = GC_REALLOC(q, 2 * sizeof(int));
        if (i % 100000 == 0)
            printf("Heap size = %zu\n", GC_get_heap_size());
    }

    return 0;
}

1 Ответ

2 голосов
/ 02 августа 2011

Я думаю, что вы должны аннотировать сам API BoehmGC , и тогда аннотации, необходимые для примера (если есть), станут очевидными.

Для начала, любой указатель, возвращаемый функцией без аннотации, неявно равен @only, что означает, что вы должны освободить связанную память до потери ссылки . Следовательно, первым шагом будет аннотирование распределителей, чтобы они больше не возвращали ссылку @only. Вместо этого руководство рекомендует использовать общие ссылки :

Если Splint используется для проверки программы, предназначенной для использования в Среда сбора мусора, может быть хранилище, которое совместно используется одна или несколько ссылок и никогда явно не выпущены. Общий аннотация объявляет хранилище, которое может быть разделено произвольно, но никогда освобожден.

Если вы не хотите изменять API BoehmGC, вы можете обойти его, создав должным образом аннотированные функции-оболочки. Кроме того, вам нужно будет отключить определенные ошибки передачи в ваших функциях-оболочках (потому что они получают неявную ссылку @only из API BoehmGC и затем возвращают ее как @shared).

Например, таким способом вы могли бы отключить «Оператор не имеет эффекта» в определенной точке вашего кода:

/*@-noeffectuncon@*/
not_annotated_void_function();
/*@=noeffectuncon@*/

Функция-оболочка будет выглядеть примерно так:

/*@shared@*/ /*@null@*/ /*@out@*/ static void * MY_GC_MALLOC(size_t size) /*@*/{
    /*@-onlytrans@*/
    return( GC_MALLOC(size) );
    /*@=onlytrans@*/
}

Тогда в примере вы будете использовать MY_GC_MALLOC вместо GC_MALLOC.

...