Подтвердить что ты не робот

Как проверить, освобожден ли указатель уже в C?

Я хочу проверить, освобожден ли указатель уже или нет. Как это сделать с помощью набора компиляторов gnu?

Спасибо,

4b9b3361

Ответ 1

Вы не можете. Путем отслеживания этого было бы назначить указатель на 0 или NULL после его освобождения. Однако, как заметил Фред Ларсон, это ничего не делает с другими указателями, указывающими на одно и то же место.

int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;

Ответ 2

Вы не можете. Просто присвойте ему NULL после free, чтобы убедиться, что вы не освобождаете его дважды (это нормально free(NULL)).

Еще лучше, если возможно, не пишите код, где вы "забываете", что уже освободили его.

ИЗМЕНИТЬ

Интерпретация вопроса: как определить, освобождена ли указательная память, указанная указателем: вы не можете этого сделать. Вы должны делать свою собственную бухгалтерию.

Ответ 3

Нет надежного способа узнать, освобожден ли указатель, как заметил Грег, освобожденная память может быть занята другими нерелевантными данными, и вы получите неправильный результат.

И действительно, нет стандартного способа проверить, освобожден ли указатель. Тем не менее, glibc имеет функции (mcheck, mprobe), чтобы найти статус malloc указателя для проверка согласованности кучи, и один из них - видеть, освобожден ли указатель.

Однако, эти функции в основном используются только для отладки, а не являются потокобезопасными. Если вы не уверены в этом требовании, избегайте этих функций. Просто убедитесь, что у вас есть парная malloc/free.


Пример http://ideone.com/MDJkj:

#include <stdio.h>
#include <stdlib.h>
#include <mcheck.h>

void no_op(enum mcheck_status status) {}

int main()
{
    mcheck(&no_op);

    void* f = malloc(4);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);

    free(f);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);

    return 0;
}

Ответ 4

Вы можете расширить концепцию назначения NULL значению указателя, написав макрос, который сделает это за вас. Например:

#define FREE(ptr) do{ \
    free((ptr));      \
    (ptr) = NULL;     \
  }while(0)

Затем, пока вы убедитесь, что ваш код использует только FREE(), а не free(), вы можете быть достаточно уверены, что код, который вы написали, не освобождает одну и ту же память дважды. Конечно, это не делает ничего, чтобы предотвратить множественные вызовы в библиотечные функции, которые освобождают память. И он не делает ничего, чтобы гарантировать, что для каждого malloc есть бесплатный.

Вы можете попробовать это с помощью функции, но она становится неудобной, потому что вам нужно бросить оператор-справочник, и он больше не похож на обычный вызов free().

Ответ 5

Вы этого не сделаете, потому что не можете.

Следите за указателями, которые вы получаете от malloc(), и только освободите их, и только один раз.

Если вы это сделаете, память не имеет памяти, поэтому она не знает, выделено ли это или нет. Только ваш менеджер памяти ОС может сказать вам, что (но C не содержит стандартизованного механизма для запроса этой информации).

Ответ 6

Я знаю, что этот ответ a little bit поздний, но я просто прочитал этот ответ и написал код для проверьте следующее:

Free поместит блок памяти в собственный список свободных блоков. Обычно он также пытается объединить соседние блоки в адресном пространстве. Список свободных блоков - это всего лишь круговой список фрагментов памяти, которые, конечно же, имеют некоторые данные администратора в начале. Свободный список также в первом местоположении, malloc ищет новый кусок памяти, когда это необходимо. Сканируется, прежде чем он вызывает новую память из ОС. Когда найден фрагмент, который больше, чем необходимая память, он просто делится на две части. Один возвращается абоненту, другой возвращается в свободный список.

Этот код проверяет, освобожден ли первый указатель, который был выделен:

int is_freed(void *p)
{
    void * q;
    char p_addr [50];
    char q_addr [50];

    sprintf(p_addr, "%p", p);

    q = malloc (1);
    sprintf(q_addr, "%p", q);
    free (q);

    return ! strcmp(q_addr, p_addr);
}

Я тестировал этот код на HP-UX и Linux Redhat, и он работает, для случая только одного указателя.