2016-07-14 3 views
1

Ich arbeite an einem Projekt, das Multithreading beinhaltet. Obwohl ich ein ordentliches Verständnis für Multithreading habe, habe ich nicht viele solche Codes geschrieben. Der folgende Code ist nur ein einfacher Code, den ich für den praktischen Gebrauch geschrieben habe. Es funktioniert gut, wenn es mit gcc -pthread kompiliert wird.Einen Fehler in einem einfachen Multithreading-Programm nicht festhalten können

Um auf diesem Code aufzubauen, muss ich einige Bibliotheken einschließen, die bereits pthread enthalten und verknüpft haben. Wenn ich kompiliere, indem ich diese Bibliotheken einschließe und verlinke, gibt es 3 von 5 Malen einen Segmentierungsfehler. Es gibt ein Problem mit den ersten für -loop in main() - ersetzt diesen für -loop mit mehreren Anweisungen machen die Arbeit.

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <pthread.h> 

#define NUM_THREADS 3 

pthread_mutex_t m_lock = PTHREAD_MUTEX_INITIALIZER; 

typedef struct{ 
    int id; 
    char ip[20]; 
} thread_data; 

void *doOperation(void* ctx) 
{ 
    pthread_mutex_lock(&m_lock); 
    thread_data *m_ctx = (thread_data *)ctx; 
    printf("Reached here\n"); 
    pthread_mutex_unlock(&m_lock); 
    pthread_exit(NULL); 
} 

int main() 
{ 
    thread_data ctx[NUM_THREADS]; 
    pthread_t threads[NUM_THREADS]; 

    for (int i = 0; i < NUM_THREADS; ++i) 
    { 
     char ip_n[] = "127.0.0."; 
     char ip_h[4]; 
     sprintf(ip_h, "%d", i+1); 
     strcpy(ctx[i].ip, strcat(ip_n, ip_h)); 
    } 

    for (int i = 0; i < NUM_THREADS; ++i) 
    { 
     pthread_create(&threads[i], NULL, doOperation, (void *)&ctx[i]) 
    } 

    for (int i = 0; i < NUM_THREADS; ++i) 
    { 
     pthread_join(threads[i], NULL); 
    } 

    pthread_exit(NULL); 

} 
+0

'strcat (ip_n, ip_h)' - ruft * undefiniertes Verhalten * auf, wenn 'ip_h' keinen Inhalt hat. – WhozCraig

+0

Aber ip_h hat Inhalt - die String-Version von (i + 1). Ich meine "1", wenn ich 0 ist. –

+1

@SonuMishra, ja, das ist das Problem. –

Antwort

3

Sie sagen, dass der Code, den Sie present "funktioniert gut", aber es ist fehlerhaft. Insbesondere ist die erste for Schleife fehlerhaft, so ist es nicht verwunderlich, dass es Ihnen Mühe unter Umständen gibt. Hier ist eine Aufschlüsselung:

char ip_n[] = "127.0.0."; 

Sie haben ip_n erklärt, wie ein Array von char genau lang genug, um die gegebenen initializer zu halten, einschließlich der abschließenden Nullzeichen.

char ip_h[4]; 
    sprintf(ip_h, "%d", i+1); 

Annahme, dass die sprintf() erfolgreich ist, haben Sie ip_h eine nicht leere Zeichenfolge in char Array geschrieben.

strcpy(ctx[i].ip, strcat(ip_n, ip_h)); 

Sie versuchen, über strcat() den Inhalt ip_h bis Ende ip_n anzuhängen, aber es gibt keinen Raum - dies schreibt über die Grenzen des ip_n, nicht definiertes Verhalten zu erzeugen.

Der einfachste Weg, dies zu lösen, wäre wahrscheinlich, ip_n mit einer expliziten Länge anzugeben, die für die vollständigen Daten ausreicht. Im Allgemeinen erfordert eine IP-Adressfolge mit Punkten vier bis zu 16 Bytes, einschließlich des Abschlusszeichens:

char ip_n[16] = "127.0.0."; 
1

Habe ich nur noch ; am Ende pthread_create(&threads[i], NULL, doOperation, (void *)&ctx[i])

Und diese Segmentierungsfehler könnte, weil sein von

char ip_n[] = "127.0.0.";

oben, nur die sizeof(ip_n)9 zurückgibt. Aber Sie brauchen mindestens 10 Zeichen zum Speichern von String wie 127.0.0.3 (Einschließlich Nullzeichen am Ende). Nicht autorisierter Speicherzugriff kann zu einem Segmentierungsfehler führen. Ersetzen Sie dies durch char ip_n[10] = "127.0.0.";

+0

Das war nur ein Tippfehler, als ich die Frage hier geschrieben habe. Finden Sie irgendein Problem mit der ersten for-Schleife? Wie ich in meiner Frage erwähnt habe, funktioniert der Code gut, wenn er explizit mit Pthread kompiliert wird. –

+0

Ich denke, ich fand es ... Bitte überprüfen Sie die bearbeitete Antwort .. –

1

Sie können nicht strcat(ip_n, ip_h), weil das Array ip_n nur groß genug ist, um die Zeichenfolge "127.0.0." zu halten. Hier ist, was der Mann Seite sagt, Betonung hinzugefügt

Die strcat() und strncat() -Funktionen anhängen eine Kopie des nullterminierten String s2 bis zum Ende des nullterminierten String s1, dann fügen Sie ein Beenden von `\ 0 '. Der String s1 muss ausreichend Raum hat das Ergebnis zu halten.

sollte die Erklärung

sein
char ip_n[20] = "127.0.0."; 
0

ip_n [] zeigt auf eine Konstante; der Compiler reserviert 9 Bytes einschließlich des NULL-Bytes. Auf alles nach diesen 9 Bytes sollte nicht zugegriffen werden, und wenn Sie dies tun, ist das Ergebnis undefiniert (es könnte einige Zeit funktionieren, aber wahrscheinlich nicht die ganze Zeit). Wenn Sie dies tun:

Sie überlaufen den Puffer, auf den ip_n zeigt. Vielleicht verursacht das Ihr Problem. Wenn es nicht ist, empfehle ich immer noch, dies zu beheben.

+1

Ja, er ist überfüllt 'ip_n'. Nein, 'ip_n' zeigt nicht auf eine Konstante. Es zeigt tatsächlich nichts an, weil es ein Array ist, kein Zeiger. Das String-Literal in der Deklaration von 'ip_n' ist ein * Initialisierer *. –

+0

Eine Array-Variable in C enthält die Adresse ihres ersten Elements. Es ist ein konstanter Zeiger und Sie können es nicht ändern, nachdem es deklariert wurde. Darüber hinaus zeigt Ihre Array-Variable auf eine konstante Zeichenfolge litteral. Sie können Folgendes tun: p [0] oder * p, wodurch Sie das erste Element wie in printf erhalten ("% c", * ip_n) ;. Wenn Sie das zweite Element möchten, könnten Sie printf ("% c", * (ip_n + 1)); Ich verweise auf https://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays unter der Überschrift "Pointers and Arrays" Prost :-) –

+0

Ein Array ist kein Zeiger, Punkt. In dem Maße, in dem das Wikibook anders vorschlägt, ist es zu stark vereinfachend. Wenn ein Array in einem Ausdruck erscheint, verfällt es in den meisten Kontexten * zu einem Zeiger auf sein erstes Element, aber dies unterscheidet sich erheblich von einem *, der ein Zeiger auf das erste Element ist. Es gibt eine Vielzahl von Wegen, auf denen Sie unterscheiden können, wobei der "Size of" -Operator von Bedeutung ist. –

Verwandte Themen