Моя программа вылетает с ошибкой сегментации при нормальной работе. Поэтому я запускаю его с помощью gdb, но он не будет терпеть крах, когда я это сделаю. Кто-нибудь знает, почему это может произойти? Я знаю, что Valgrind faq упоминает это (не разбивается под valgrind), но я не мог найти ничего об этом, связанном с gdb в google. Если кто-то скажет мне, почему, или рекомендую что-то искать, когда это произойдет, я был бы очень благодарен.
Сбой обычно, но не с GDB?
Ответ 1
Хорошо, я отследил его до вызова pthread_detach. Я делал pthread_detach (& thethread). Я просто забрал ссылку и изменил ее на pthread_detach (thethread), и она отлично работала. Я не уверен, но, может быть, он был свободен от двойки, отделив ссылку, затем уничтожив ее снова, когда она вышла из сферы действия?
Ответ 2
У меня это случалось со мной раньше (вы не одиноки), но я не могу вспомнить, что я сделал, чтобы исправить ситуацию (я думаю, что это был двойной свободный).
Мое предложение состояло в том, чтобы настроить среду для создания дампов ядра, а затем использовать GDB для исследования дампа ядра после сбоя программы. В bash это делается с помощью ulimit -c size
, где размер может быть любым; Я лично использую 50000 для максимального размера 25 МБ; блок имеет шаг в 512 байт.
Вы можете использовать GDB для исследования дампа ядра с помощью gdb program core
.
Ответ 3
Звучит как Heisenbug, который у вас есть: -)
Если платформа, с которой вы работаете, может создавать основные файлы, она должна иметь возможность использовать основной файл и gdb, чтобы определить местоположение, где происходит сбой программы - можно найти краткое описание здесь.
Пусть он падает пару раз, хотя, когда авария вызвана разбитием стека или переменной перезаписью, ошибка может казаться "ходить".
Ответ 4
Попробуйте подключиться к текущему процессу в gdb
, продолжая, а затем воспроизводя крах. Другими словами, не запускайте программу в gdb
; вместо этого запустите программу нормально, а затем attach <pid>
.
Иногда, когда вы переходите по строкам индивидуально, состояние гонки, которое приводит к сбою программы, не будет проявляться, поскольку опасность гонки была устранена или сделана чрезвычайно невероятной благодаря "длительным" паузам между этапами.
Ответ 5
Проверить возвращаемое значение вызова pthread_detach
. Согласно вашему ответу, вы, вероятно, передаете недействительный дескриптор потока на pthread_detach
.
Ответ 6
Если ошибка зависит от времени, gdb может помешать повторению.
Ответ 7
Я тоже это случалось со мной несколько раз.
Мое решение: очистить и перестроить все.
Не говоря о том, что это всегда решает все проблемы (и в случае OP проблема была что-то действительно неправильно), но вы можете сэкономить некоторые проблемы и время, если вы сделаете это сначала, когда столкнетесь с такими действительно странные "мета" ошибки. По крайней мере, по моему опыту, такие вещи чаще всего происходят из старых объектных файлов, которые нужно было перестроить, но не были. Как в MinGW, так и в обычном GCC.
Ответ 8
У меня была аналогичная проблема, в моем случае она была связана с указателями в структуре связанных ссылок. Когда я динамически создавал новый список без инициализации всех указателей внутри структуры, моя программа вылетает наружу GDB
Вот мои исходные структуры данных:
typedef struct linked_list {
node *head;
node *tail;
} list;
typedef struct list_node {
char *string;
struct list_node *next;
} node;
Когда я создал новый "экземпляр" list
с указанием его head
и tail
, программа вылетела наружу DGB
:
list *createList(void) {
list *newList = (list *) malloc(sizeof(list));
if (newList == NULL) return;
return newList;
}
Все началось нормально, после того как я изменил функцию createList
на это:
list *createList(void) {
list *newList = (list *) malloc(sizeof(list));
if (newList == NULL) return;
newList->head = (node *) 0;
newList->tail = (node *) 0;
return newList;
}
Надеюсь, что это может помочь кому-то в случае чего-то похожего на мой пример с неинициализированными указателями.
Ответ 9
Когда вы запускаете свой код с помощью gdb, он перемещается. Теперь незаконный адрес, с которым вы пытались ссылаться раньше - тот, который вызвал segfault, - это законно. Это боль, конечно. Но лучший способ, которым я знаю, отслеживать такую ошибку, - начать вкладывать в printf() все по всему месту, постепенно сужая ее.