2012-09-13 3 views
2

Я учусь PTHREAD, следующий мой простой код:вина сегмента на PTHREAD

1 #include <pthread.h> 
    2 #include <cstdlib> 
    3 #include <iostream> 
    4 #include <string> 
    5 #include <sstream> 
    6 
    7 using namespace std; 
    8 
    9 struct ThreadParam 
10 { 
11  int thread_id; 
12  string message; 
13 }; 
14 
15 string int2string(int i) 
16 { 
17  stringstream s; 
18  s << i; 
19  return s.str(); 
20 } 
21 
22 void * Hello(void * param) 
23 { 
24  ThreadParam * threadParam = (ThreadParam*)param; 
25 
26  int tid = threadParam->thread_id; 
27  string msg = threadParam->message; 
28  string output = msg + " In thread " + int2string(tid); 
29 
30  cout << output << endl; 
31  pthread_exit(NULL); 
32 } 
33 
34 int main() 
35 { 
36  const int count = 30; 
37  ThreadParam params[count]; 
38 
39  pthread_t threads[count]; 
40  int rc; 
41  for(int t=0; t < count; t++) 
42  { 
43   cout << "In main: creating thread " << t << endl; 
44 
45   params[t].thread_id = t; 
46   params[t].message = "Hello " + int2string(t) + "!"; 
47 
48   rc = pthread_create(&threads[t], NULL, Hello, (void*)&params[t]); 
49 
50   if(rc) 
51   { 
52    cout << "Error! Return code is " << rc << endl << flush; 
53    exit(-1); 
54   } 
55  } 
56  pthread_exit(NULL); 
57 } 

я получил ошибку сегментации после создания последнего потока. Выходной сигнал:

In main: creating thread 0 
In main: creating thread 1 
In main: creating thread 2 
In main: creating thread 3 
In main: creating thread 4 
In main: creating thread 5 
In main: creating thread 6 
In main: creating thread 7 
In main: creating thread 8 
In main: creating thread 9 
In main: creating thread 10 
In main: creating thread 11 
Hello 0! In thread 0 
Hello 1! In thread 1 
Hello 2! In thread 2 
Hello 3! In thread 3 
Hello 4! In thread 4 
In main: creating thread 12 
In main: creating thread 13 
In main: creating thread 14 
In main: creating thread 15 
In main: creating thread 16 
In main: creating thread 17 
In main: creating thread 18 
In main: creating thread 19 
In main: creating thread 20 
In main: creating thread 21 
In main: creating thread 22 
In main: creating thread 23 
In main: creating thread 24 
In main: creating thread 25 
In main: creating thread 26 
In main: creating thread 27 
In main: creating thread 28 
In main: creating thread 29 
Segmentation fault 

Я не могу понять, почему, какой-либо ключ?

+3

Вы пытались вызвать 'pthread_join'? – cnicutar

+0

Вы использовали gdb, чтобы отладить свою проблему и посмотреть, где вы получаете ошибку seg и почему? Мы не можем тебе помочь, пока ты не будешь терпеть. – bmargulies

+0

В соответствии с http://stackoverflow.com/questions/3559463/is-it-ok-to-call-pthread-exit-from-main 'pthread_exit' в главном случае не нужно присоединяться к потокам. Поэтому я задаюсь вопросом, является ли 'cout << output' потоком небезопасным и может вызвать проблемы: http://stackoverflow.com/questions/6374264/is-cout-synchronized-thread-safe –

ответ

3

Посмотрев на свой код, я могу сказать, что после создания последнего потока вы уничтожаете главный (поток создателя). Это приводит к тому, что стек этой нити будет освобожден. Но поскольку вы используете указатели на основную стек стека потоков (ThreadParam params[count];, если быть точным, вы передаете указатели на него в функцию pthread_create), тогда вы попытаетесь прочитать неверные данные в других потоках. Страницы памяти, выделенные для основного потока потоков, были отмечены как «неиспользуемые» или «нераспределенные» после уничтожения основного потока, поэтому вы получаете segfault при попытке получить к ним доступ.

UPD: Как уже было сказано, вы должны использовать функцию pthread_join, чтобы ждать завершения всех потоков, а затем уничтожить основной поток.

+0

+1 для 'ThreadParam params [count]' уничтожается до того, как поток обращается к его параметру –

+0

О, я вижу. Я сделал глупую ошибку. Код примера, который я прочитал, делает этот массив глобальным. Мне не нравятся глобальные переменные и объявлены в основном и приводят к этой ошибке. – Ryan

2

Перед тем, как выйти из программы, вам нужно подождать, пока не закончится нить. Если вы этого не сделаете - может случиться много плохого. Чтобы присоединиться к потоку, используйте pthread_join(). Вы также можете столкнуться с «отсоединенными» потоками в документации API - не пытайтесь использовать его, он не работает, по крайней мере, не в Linux.

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

+0

Проблема с отладкой и несколькими потоками связана с тем, что к различным таймингам многие проблемы в продуктивном коде не появляются во время отладки. – phlogratos

+0

@phlogratos: по этой причине есть основные свалки. Включите оптимизацию, оставьте символы отладки, выполните сбой процесса, затем запустите отладчик с ядром. –

2

Ваш основной поток должен подождать, пока ваши второстепенные потоки закончат выполнение. Это приводит к ошибке seg.

Основная резьба должна соединяться с другими резьбами.

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