Как проверить, освобожден ли указатель уже в C? - PullRequest
26 голосов
/ 28 ноября 2011

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

Ответы [ 7 ]

27 голосов
/ 28 ноября 2011

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

int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;
24 голосов
/ 28 ноября 2011

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

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

РЕДАКТИРОВАТЬ

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

14 голосов
/ 28 ноября 2011

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

И действительно, нет стандартного способа проверить, освобожден ли указатель. При этом , 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;
}
5 голосов
/ 29 ноября 2011

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

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

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

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

2 голосов
/ 28 ноября 2011

Нет, так как вы не можете.

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

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

0 голосов
/ 10 ноября 2018

Вот как я это делаю:

bool pointer_allocated(void* ptr) {
  return ptr != NULL;
}
0 голосов
/ 25 марта 2014

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

Свободно установит блок памятив свой собственный список бесплатных .Обычно он также пытается объединить смежные блоки в адресном пространстве.Список свободных блоков - это просто циклический список блоков памяти, в которых, конечно, есть некоторые данные администратора.Бесплатный список также первое местоположение , 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);
}

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

...