基本posix线程参数传递问题

时间:2016-03-30 01:07:55

标签: c multithreading arguments posix

我正试图进入线程世界并遇到麻烦。下面的代码每隔一段时间运行一次,但似乎是完全随机的。给它相同的输入不断给我不同的结果,我很困惑。 有时PrintHello()打印出参数,有时打印垃圾,有时只是段错误。

#define NUM_THREADS 5
char *prompt = "% ";

struct thread_data{
    int thread_id;
    //int sum;
    char *message;
};

void *PrintHello(void *threadarg)
{   
   struct thread_data *local_data;
   local_data = (struct thread_data *) threadarg;
   int taskid = local_data->thread_id;
   const char *arguments = local_data->message;
   fprintf(stderr, "Hello World! It's me, thread %s!\n", arguments);
   pthread_exit(NULL);
}

PrintHello()是我认为问题所在。

int main()
{
    int pid;
    //int child_pid;
    char line[81];
    char *token;
    char *separator = " \t\n";
    char **args;
    char **args2;
    char *hp;
    char *cp;
    char *ofile;
    int i;
    int j, h, t, rc;

    args = malloc(80 * sizeof(char *));
    args2 = malloc(80 * sizeof(char *));

    signal(SIGINT, SIG_IGN);

    while (1) {
        fprintf(stderr, "%s", prompt);
        fflush(stderr);

        if (fgets(line, 80, stdin) == NULL)
            break;

       /* get rid of the '\n' from fgets */
        if (line[strlen(line) - 1] == '\n'){
               line[strlen(line) - 1] = '\0';
    }
    // split up the line

    i = 0;
    while (1) {
        token = strtok((i == 0) ? line : NULL, separator);
        if (token == NULL)
            break;
        args[i++] = token;
    }

    args[i] = NULL;
    ofile = args[i-1];
    printf("%s\n", ofile);

上面的内容只是标记输入并且工作正常。

    struct thread_data thread_data_array[i];
    pthread_t threads[i];



    for(t=0; t<i; t++){

        thread_data_array[t].thread_id = t;
        thread_data_array[t].message = args[t];

        rc = pthread_create(&threads[t], NULL, PrintHello, (void *)&thread_data_array[t]);
        if (rc){
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
  }
}      
}

1 个答案:

答案 0 :(得分:1)

您的代码存在一些问题,但我会关注影响稳定性的关键问题。

  1. 您未检查malloc()的返回值。如果返回值为NULL,则表示操作失败,您必须重新尝试,或者从malloc()calloc()strdup()等开始清理所有动态分配的内存。 ,优雅地完成你的程序。尝试取消引用NULL(即:使用失败的内存分配调用中的指针)将使程序崩溃。
  2. 您的程序没有考虑提供的零有效参数(即:只是在提示符处按 ENTER 。将所有换行符实例更改为'\0' ,并继续。
  3. 此外,计算您发现的令牌数量。良好的做法,并帮助您检查是否找不到有效的输入。
  4. 考虑阅读starting threads in a detached state versus a joinable state。您的代码中最大的问题是您启动所有线程,然后您的while循环立即再次执行,并重新为thread[]数组分配新值。此外,相同的参数在仍在使用时传递给它们(thread_data_array[t]),并且您没有保护它们的互斥锁。此外,如果你的程序main()提前退出,那么所有正在运行的线程都会立即被终止,并且无法完成。
  5. 您应该pthread_join()关于可连接的线程,以确保您在完成之前等到它们完成。
  6. 如果不使用 CTRL + C 或使其崩溃,则无法退出程序。不是个好主意。
  7. 请注意,线程不一定按照您创建它们的顺序执行,尽管在这种情况下幸运。您需要了解障碍,条件变量(condvars)和互斥体以进行更高级的同步处理。
  8. 您错过了许多重要的标头文件。惊讶你的代码编译。
  9. Learn how to debug your code with gdb. In this case, I compiled it via gcc test.c -lpthread -O0 -ggdb, then stepped through the code via the "next" n command after starting it in gdb with run. It makes your life a lot easier
  10. 更新了代码清单

    #include <stdio.h>
    #include <signal.h>
    #include <pthread.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define NUM_THREADS 5
    #define BUF_LEN (80)
    char *prompt = "% ";
    
    struct thread_data{
        int thread_id;
        //int sum;
        char *message;
    };
    
    void *PrintHello(void *threadarg)
    {   
        struct thread_data *local_data;
        local_data = (struct thread_data *) threadarg;
        int taskid = local_data->thread_id;
        const char *arguments = local_data->message;
        fprintf(stderr, "Hello World! It's me, thread %s!\n", arguments);
        pthread_exit(NULL);
    }
    
    int main()
    {
        int pid;
        //int child_pid;
        char line[81];
        char *token;
        char *separator = " \t\n";
        char **args;
        char **args2;
        char *hp;
        char *cp;
        char *ofile;
        int i;
        int j, h, t, rc;
    
        args = malloc(BUF_LEN * sizeof(char *));    // ISSUE: Can fail. Check return value.
        args2 = malloc(BUF_LEN * sizeof(char *));   // ISSUE: Can fail.
    
        signal(SIGINT, SIG_IGN);
    
        while (1)
        {
            fprintf(stderr, "%s", prompt);
            fflush(stderr);
    
            if (fgets(line, BUF_LEN, stdin) == NULL)
            {
                break;
            }
    
            /* get rid of the '\n' from fgets */
            /*
            if (line[strlen(line) - 1] == '\n'){
                line[strlen(line) - 1] = '\0';
            }
            */
            for ( t = 0; t < BUF_LEN; t++ )
            {
                if ( line[t] == '\n' )
                {
                    line[t] = '\0';
                }
            }
    
            // split up the line
            i = 0;
            int numTokens = 0;
            while (1) {
                token = strtok((i == 0) ? line : NULL, separator);
                if (token == NULL)
                {
                    break;
                }
                args[i++] = token;
                numTokens++;
            }
            // Abort if zero tokens found.
            if ( numTokens == 0 )
            {
                continue;
            }
            // Exit if input is "quit"
            if ( strcasecmp(line, "quit") == 0 )
            {
                break;
            }
    
            args[i] = NULL;
            ofile = args[i-1];
            printf("%s\n", ofile);
            struct thread_data thread_data_array[i];
            pthread_t threads[i];
    
            for(t=0; t<i; t++)
            {
                thread_data_array[t].thread_id = t;
                thread_data_array[t].message = args[t];
    
                rc = pthread_create(&threads[t], NULL, PrintHello, (void *)&thread_data_array[t]);
                if (rc)
                {
                    printf("ERROR; return code from pthread_create() is %d\n", rc);
                    exit(-1);
                }
            }
    
            // Wait for threads to complete work.
            for(t=0; t<i; t++)
            {
                pthread_join(threads[t], NULL);
            }
        }      
    }
    

    样本运行

    % 
    % 
    % 
    % Hello world. This is a test
    test
    Hello World! It's me, thread test!
    Hello World! It's me, thread a!
    Hello World! It's me, thread is!
    Hello World! It's me, thread This!
    Hello World! It's me, thread world.!
    Hello World! It's me, thread Hello!
    % 
    % 1 2 3
    3
    Hello World! It's me, thread 3!
    Hello World! It's me, thread 2!
    Hello World! It's me, thread 1!
    % QUit