Первый шаг - попытаться запустить функцию без введения потоков.Просто напишите .c файл с main
, который делает минимум, чтобы подготовиться к запуску потока, а затем вместо этого просто вызывает функцию.Отладка намного проще, если вы можете воссоздать проблему только с одним потоком.
Кроме того, если вы используете gcc, вы должны скомпилировать с:
-fstack-protector-all -Wstack-protector -fno-omit-frame-pointer
в дополнение к вашим обычным флагам(по крайней мере, пока вы не найдете проблему).Это поможет с отладкой и, возможно, выдаст больше предупреждений во время компиляции.Я предполагаю, что вы знаете, как -O
флаги могут влиять на способность и функциональность отладки (особенно, если вы уже делаете что-то неправильно или неопределенно в коде C).
Когда вы находитесь в GDB и все выглядит так, как будто онизаблокирован или программа занимает много времени, чтобы сделать что-то, вы обычно можете нажать CTRL Z
, чтобы вернуться к (gdb)
, не убивая программу.Это подает сигнал остановки программе и позволяет вам снова взаимодействовать с GDB, чтобы вы могли узнать, что на самом деле делает программа.комментарии обсуждение, поэтому я напишу, в чем здесь проблема.
Быстрый взгляд на код не выявил проблемы, которая привела бы к ошибке сегментации (незаконный доступ к памяти), и Zypsy (OP) сказал мне, что функция работала нормально, когда вызывался напрямую из main, а не через отдельный поток.
Valgrind сообщил, что пространство стека потока не может быть расширено до определенного адреса.В Linux стек основного потока отображается в приложении таким образом, что он может легко расти, но это часто не делается, когда память выделяется для стеков потоков.
Я попросил Zypsy (OP):вставьте некоторый код, который будет распечатывать адрес чего-то, что известно как низкий в стеке потоков (printf("thread stk = %p\n", &input);
), чтобы это значение можно было сравнить с адресом, указанным в сообщении об ошибке.Исходя из этого, я мог предположить размер стека.Это не предполагало, что между началом функции потока и ее ошибкой потреблялось очень много стекового пространства, но пространство также не выглядело слишком маленьким для рассматриваемого кода (хотя, по-видимому, оно оказалось слишком маленьким).
Поскольку функция pthread_create
позволяет вам принять настройки для атрибутов потока (передать NULL
) или передать аргумент, указывающий различные настройки для потока, я спросил, является ли код, вызвавший pthread_create
можно опубликовать, чтобы я мог увидеть, есть ли какие-либо подозрительные настройки.
После просмотра этого кода (специфическая оболочка приложения для различных pthread_
функций) я обнаружил, что на самом деле существует какой-то стекатрибуты устанавливаются.Я попросил OP посмотреть на вызовы этой функции и найти подозрительные вещи, связанные с тем, как был выделен стек (убедитесь, что значение размера и размер выделенной памяти фактически совпадают).Оказалось, что OP обнаружил, что стек этого потока выделяется меньше, чем стеки других потоков.Стек был слишком маленьким.