2015-10-18 3 views
0

У меня возникли проблемы, идентифицирующие почему Valgrind бросает эту ошибку:Valgrind метания необъяснимой ошибки в потоке

==82185== Thread 2: 
==82185== Use of uninitialised value of size 8 
==82185== at 0x401B9A: proc_outconnection_thread (station.c:401) 
==82185== by 0x4E3CDF4: start_thread (in /usr/lib64/libpthread-2.17.so) 
==82185== by 0x51471AC: clone (in /usr/lib64/libc-2.17.so) 
==82185== 
the pass im sending is 'this' 
==82185== Use of uninitialised value of size 8 
==82185== at 0x401BCA: proc_outconnection_thread (station.c:403) 
==82185== by 0x4E3CDF4: start_thread (in /usr/lib64/libpthread-2.17.so) 
==82185== by 0x51471AC: clone (in /usr/lib64/libc-2.17.so) 
==82185== 

Как немного справочной информации, программа я пытаюсь создать в C имитирует железнодорожную станцию который использует TCP-соединения как «поезда». Я пытаюсь заставить программу использовать потоки, чтобы как слушать, так и пытаться подключаться к другим станциям (другие экземпляры программы).

Проблема, кажется, существует при передаче внутренней структуры данных функции создания потоков с помощью структуры аргументов, содержащей указатель на внутреннюю структуру данных. Таким образом, каждый поток имеет указатель на внутренние данные программ.

В моих усилиях тестирования, файл скомпилирован с gcc -pthread -g -o station station.c -Wall -pedantic -std=gnu99

Чтобы произвести свою ошибку, начните экземпляр станции с valgrind ./station tom authf logfile 3329 127.0.1.1 , а затем начать еще один экземпляр с valgrind ./station tim authf logfile 3328 127.0.1.1

Благодаря, если заявление в основном название станции с типом будет пытаться подключиться к tom, а tom создаст сокет и прослушает попытку подключения к ним. Соединение кажется успешным, но по какой-то причине я также не могу очистить соединение, чтобы отправить что-нибудь между ними, что, по моему мнению, может быть из-за того, что говорит мне Вальгринд. Странно, что когда поток создается для соединения с экземпляром tom, никаких ошибок в valgrind не возникает, несмотря на очень похожую процедуру для создания потока (те же аргументы передаются через указатель аргументов и выполняются те же присвоения).

Может ли это быть ложным положительным для конца Тима, или я делаю что-то серьезное здесь неправильно?

+0

не ссылаются на исходный код. Разделите свой код на перевариваемый размер, который по-прежнему имеет ту же проблему и покажет его нам. –

+0

компиляция кода под ubuntu linux 14.04 с использованием 'gcc', с параметрами' -Wall -Wextra -pedantic -std-c99' приводит к длинной строке предупреждающих сообщений. Настоятельно рекомендуем зафиксировать эти предупреждения. Предупреждения о неиспользуемых переменных и неиспользуемых параметрах являются лишь признаками неаккуратного программирования, но другие предупреждения, например, о плохих параметрах для некоторых вызовов функции fprintf(), более серьезны. Примечание: строки 403 и 405 (в моем редакторе) содержат fprintf(). – user3629249

+0

В опубликованном коде есть несколько номеров 'magic'. «волшебные» номера делают код намного сложнее понять и представляют собой настоящую головную боль при выполнении обслуживания. Настоятельно рекомендуем вставлять enum или # define для этих чисел, с содержательными именами и использовать эти значащие имена во всем коде. – user3629249

ответ

1

Ваша проблема заключается в передаче указателя на локальную переменную в функцию потока. Простейшее обходное объявление объявляет эту переменную как статическую или глобальную, но это не очень хорошо, если несколько потоков используют эту переменную. лучше, чтобы выделить необходимый объем памяти для структуры, инициализировать и передать в функцию потока:

ArgStruct *argStruct = malloc(sizeof(ArgStruct)); 
if(argStruct == NULL) { 
    fprintf(stderr, "Cant alloc memory!\n"); 
    exit(98); 
} 
argStruct->internalStruct = internal; 
argStruct->clientCon = fdopen(fd, "r+"); 
pthread_create(&threadId, NULL, proc_outconnection_thread, void*)argStruct); 

И не забудьте освободить эту память (в конце proc_outconnection_thread(), например).

+0

Большое спасибо! Это устранило проблему, у меня была неправильная идея и подумал, что просто иметь указатель на локальную переменную будет достаточно, чтобы использовать другие потоки. –

2

Отслеживайте стоимость своей структуры данных internal до места, откуда она исходит, и вы увидите, что она происходит от объекта struct, который не инициализирован. Позднее вы присваиваете значения некоторым полям, но не ко всем.

Всегда инициализировать struct объекты, и в то же время часы, что у вас есть соглашение, что проясняет инициализацию, что по умолчанию (как если сделано с 0) означает, что для данного типа.

Если у вас есть, у вас действительно есть узкое место в производительности, потому что ваш компилятор не оптимизирует неиспользуемую инициализацию, подумайте об этом и сделайте это по-другому. Здесь, поскольку вы запускаете потоки и выполняете другие сложные вещи, разница никогда не будет измерима.

+0

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

Смежные вопросы