簡體   English   中英

基本posix線程參數傳遞問題

[英]Basic posix thread argument passing issue

我正在嘗試進入線程世界,但遇到了一些麻煩。 下面的代碼每隔一段時間工作一次,但似乎是完全隨機的。 給它相同的輸入會不斷給我不同的結果,我很困惑。 有時 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. 您沒有檢查malloc()的返回值。 如果返回值為 NULL,則表示操作失敗,您必須重試,或開始從malloc()calloc()strdup()等清除所有動態分配的內存,並完成您的優雅地編程。 嘗試取消引用 NULL(即:使用來自失敗的內存分配調用的指針)將使您的程序崩潰。
  2. 您的程序不考慮提供的零個有效參數(即:只需在提示符下按ENTER 鍵。將所有換行符實例更改為'\\0' ,然后繼續。
  3. 此外,計算您發現的令牌數量。 良好的實踐,並幫助您檢查是否找不到有效的輸入。
  4. 考慮閱讀處於分離狀態與可連接狀態的啟動線程 您代碼中最大的問題是您啟動了所有線程,然后您的while循環立即再次執行,並將新值重新分配給thread[]數組。 此外,相同的參數在仍在使用時傳遞給它們( thread_data_array[t] ),並且您沒有互斥體來保護它們。 此外,如果您的程序的main()提前退出,那么所有正在運行的線程都會立即被終止,並且無法完成。
  5. 您應該在可連接線程上使用pthread_join()以確保在繼續之前等待它們完成。
  6. 您無法在不使用CTRL + C或使其崩潰的情況下退出程序。 不是個好主意。
  7. 請注意,線程不一定按照您創建它們的順序執行,盡管在這種情況下它們很幸運。 您需要了解障礙、條件變量(condvars)和互斥體以進行更高級的同步處理。
  8. 你錯過了很多重要的頭文件 驚訝你的代碼編譯。
  9. 了解如何使用 gdb 調試代碼。 在這種情況下,我通過gcc test.c -lpthread -O0 -ggdb編譯它,然后在使用run在 gdb 中啟動它后通過“next” n命令逐步執行代碼。 它讓你的生活輕松很多

更新代碼清單


#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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM