Я хочу проверить, освобожден ли указатель уже или нет. Как это сделать с помощью набора компиляторов gnu?
Спасибо,
Я хочу проверить, освобожден ли указатель уже или нет. Как это сделать с помощью набора компиляторов gnu?
Спасибо,
Вы не можете. Путем отслеживания этого было бы назначить указатель на 0
или NULL
после его освобождения. Однако, как заметил Фред Ларсон, это ничего не делает с другими указателями, указывающими на одно и то же место.
int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;
Вы не можете. Просто присвойте ему NULL
после free
, чтобы убедиться, что вы не освобождаете его дважды (это нормально free(NULL)
).
Еще лучше, если возможно, не пишите код, где вы "забываете", что уже освободили его.
Интерпретация вопроса: как определить, освобождена ли указательная память, указанная указателем: вы не можете этого сделать. Вы должны делать свою собственную бухгалтерию.
Нет надежного способа узнать, освобожден ли указатель, как заметил Грег, освобожденная память может быть занята другими нерелевантными данными, и вы получите неправильный результат.
И действительно, нет стандартного способа проверить, освобожден ли указатель. Тем не менее, 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;
}
Вы можете расширить концепцию назначения NULL значению указателя, написав макрос, который сделает это за вас. Например:
#define FREE(ptr) do{ \
free((ptr)); \
(ptr) = NULL; \
}while(0)
Затем, пока вы убедитесь, что ваш код использует только FREE(), а не free(), вы можете быть достаточно уверены, что код, который вы написали, не освобождает одну и ту же память дважды. Конечно, это не делает ничего, чтобы предотвратить множественные вызовы в библиотечные функции, которые освобождают память. И он не делает ничего, чтобы гарантировать, что для каждого malloc есть бесплатный.
Вы можете попробовать это с помощью функции, но она становится неудобной, потому что вам нужно бросить оператор-справочник, и он больше не похож на обычный вызов free().
Вы этого не сделаете, потому что не можете.
Следите за указателями, которые вы получаете от malloc()
, и только освободите их, и только один раз.
Если вы это сделаете, память не имеет памяти, поэтому она не знает, выделено ли это или нет. Только ваш менеджер памяти ОС может сказать вам, что (но C не содержит стандартизованного механизма для запроса этой информации).
Я знаю, что этот ответ 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, и он работает, для случая только одного указателя.