Quan Tran
Quan Tran

Reputation: 43

C++ multithreading: terminate after throwing an instance of 'std::length_error'

I'm learning multithreading in C++ using pthread on Tutorials Point (it might be old but I just need something to get started). I modified the code a little bit:

#include <pthread.h>
#include <iostream>
#include <string>

#define NUM_THREADS 5
#define DEBUG
#undef DEBUG

using namespace std;

struct thread_data {
    int thread_id = 0;
    string message = "";
};

void *printHello(void *threadData)
{
    struct thread_data* data = (struct thread_data*)threadData;
    int thread_id = data->thread_id;
    string message = data->message;

    cout << "From thread " << thread_id << ": " << message << "\n";
    pthread_exit(NULL);
}

int main(int argc, char** argv)
{
    pthread_t threads[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++) {
        struct thread_data* data = new thread_data();
        string message = "Special message for thread #" + to_string(i) + "!";

        #ifdef DEBUG
        cout << "DEBUG: " << "i = " << i << endl;
        #endif

        data->thread_id = i;
        data->message = message;

        cout << "main(): creating thread, " << i << endl;
        int rc = 0;
        rc = pthread_create(&threads[i], NULL, printHello, (void *) data);

        delete data;

        if (rc) {
            cout << "Error: unable to create thread: " << rc << "\n";
            return -1;
        }
    }

    pthread_exit(NULL);    
}

I compiled with:

g++ -pthread -g -Wall -std=c++11 main.cpp -o main

And the output is:

main(): creating thread, 0
main(): creating thread, 1
From thread 1: Special message for thread #1!
main(): creating thread, 2
From thread 2: Special message for thread #2!
main(): creating thread, 3
From thread 3: Special message for thread #3!
main(): creating thread, 4
From thread 4: Special message for thread #4!
terminate called after throwing an instance of 'std::length_error'
  what():  basic_string::_S_create
Aborted (core dumped)

If I don't create the threads using pthread_create and call the printHello function directly, no error occurs. Sometimes, the program would throw a segfault instead, and sometimes it ran smoothly!

Another problem is that, there should be a line saying From thread 0: Special message for thread #0! from the beginning, but there was not.

Moreover, sometimes the message "Special message for thread #n!" did not even appear, at all.

I tried initializing the struct's variables, use statically allocated memory (stack instead of heap by not using new) at line 31. I tried avoiding to use pointers in the printHello function, but since the last argument of pthread_create only accepts a pointer to the function's arguments, I couldn't do that.

My first suspicion was that there is something wrong when I assign data->message = message, so I tried assigning the string directly to data->message, but no luck. But I still think the error has to be there, since the exception is std::length_error, thrown by 'basic_string`.

Or, maybe when I pass data to pthread_create or when I make the cast at line 18, I did something wrong. My thought is that when I pass it to the function, I pass it as a pointer, cast it to a void pointer void *. When printHello received the parameter, I cast it to type thread_data*, which is a pointer, which is what it originally is.

That's when I'm able to come up with so far. Please comment if there's something obscure in my writing (English is not my first language).

Thanks everyone in advance.

Upvotes: 1

Views: 534

Answers (1)

Sander De Dycker
Sander De Dycker

Reputation: 16243

You're deleting data right after creating the thread. That means there's no guarantee the data pointer still points to a live object by the time the thread tries to access it.

You should only delete data when no-one is going to use the object any more. eg. after the thread has finished (you can use a pthread_join to achieve that eg.).

Upvotes: 3

Related Questions