LINUX.ORG.RU

Отладка падения на вызове free

 ,


0

2

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

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

Брейки на запись ставить не вариант - записей много. Как еще такое дебажить?



Последнее исправление: beastie (всего исправлений: 1)

например printf() перед всеми free() с печатью имени файла, номера строки и значения указателя.

x0r ★★★★★
()
Последнее исправление: x0r (всего исправлений: 1)

Лучше, конечно, написать свою обёртку над free (один для всех типов) и malloc (для каждого типа). Типа так:

char *mm_alloc_char(int size)
{
	if (size < 1)
	{
		fprintf(stderr, "mm_alloc_char: size is too small\n");
		return NULL;
	}

	char *data = calloc(size, sizeof(char));
	if (!data)
	{
		fprintf(stderr, "mm_alloc_char: unable to allocate %d\n", size);
		return NULL;
	}

	return data;
}

void mm_free_char(char *data)
{
	free(data);
	data = NULL;
}

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

И printf вставить, да.

post-factum ★★★★★
()
Последнее исправление: post-factum (всего исправлений: 1)

valgrind что-то писал? он же спец по таким делам.

frozenix ★★★
()

Через valgrind прогони.

UVV ★★★★★
()
Ответ на: комментарий от post-factum

Присвоение NULL после free() имеет смысл. Но в твоём примере нет, так как изменяется локальный указатель.

gman
()

mtrace же. Как раз для этого.

elfy
()

r/w бряк на выделенные байты да и все ... в дебуге удаляемая память заполняется паттерном ... можно даже бряк влупить на запись конкретного байта (это что бы не словить бряк на обычных операциях с кучей для чего она и выделялась) отловиш место первого освобождения гарантированно... я так искал ...

anonymous
()
Ответ на: комментарий от post-factum

Тоже стараюсь аккуратно использовать указатели

post-factum

http://stackoverflow.com/questions/1025589/setting-variable-to-null-after-free

Пример:

int main(void) {
  ...
  char *out_intgr = NULL; // Инициализировать указатель
  ...
  out_intgr = (char*) malloc( ( length + 1 ) * sizeof(char) ); // Зарезервировать память
  if (out_intgr == NULL) return -3; // Если не удалось зарезервировать, завершить программу
  ...
  free(out_intgr); // Освободить память буфера
  out_intgr = NULL;
  ...
}

char get_char(int f) {
  ...
  // Если память буфера зарезервирована, освободить её
  if (out_intgr != NULL) free(out_intgr);
  exit(-4);
}

См. исходный ход примера полностью

Deleted
()
Последнее исправление: Deleted (всего исправлений: 3)

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

Перед free: if( ptr != NULL ), в начале free: if( ptr != NULL ), осталось еще после free проверить.

anonymous
()
Ответ на: комментарий от anonymous

anonymous

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

Спасибо за отклик, мне известно о данной возможности free().

char get_char(int f) {
  ...
  // Если память буфера зарезервирована, освободить её
  if (out_intgr != NULL) free(out_intgr);
  ...
}

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

Deleted
()
Ответ на: комментарий от Deleted

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

anonymous
()
Ответ на: комментарий от anonymous

anonymous

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

Согласен в данном вопросе.
Дополнительную проверку if () добавил с целью обратить внимание читающего исходный код, что в указанном месте программы существует вероятность вызова free(NULL).

Deleted
()
Ответ на: комментарий от Deleted

Если читающий код окажется твоим будущим работодателем, то ты можешь сильно потерять в зарплате и в качестве задач тебе поручаемых в дальнейшем. ;)

anonymous
()
Ответ на: комментарий от anonymous

Cypher

Если читающий код окажется твоим будущим работодателем, то ты можешь сильно потерять в зарплате и в качестве задач тебе поручаемых в дальнейшем. ;)

В вопросе "ты можешь сильно потерять в зарплате и в качестве задач тебе поручаемых в дальнейшем" не согласен. ;)

Deleted
()
Последнее исправление: Deleted (всего исправлений: 5)
Ответ на: комментарий от post-factum

post-factum

Почему не calloc?

По-моему, malloc() выполняет поставленную задачу нормально.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.