代码之家  ›  专栏  ›  技术社区  ›  Amit

如果调用pthread_create,则GCC分段错误

  •  0
  • Amit  · 技术社区  · 6 年前

    这段代码似乎抛出了一个分段错误,但如果pthread_create行被注释掉,则segfault将消失。

    pthread_t thread_id[device_count];
    
    if (params.revision == 3) {
        startTime = time(NULL);
        unsigned long number = 0;
    
        deviceParams = get_device_params(platform_id, workWithUser ? "check_pdfs_user" : "check_pdfs_owner", program_buffer, program_size);
    
        int password_len = strlen(password_prefix) + password_digits + strlen(password_suffix);
    
        int j;
    
        unsigned long password_per_thread;
    
        password_t password;
        char pad[33];
        sprintf(pad, "%%s%%0%dd%%s", password_digits);
    
        while (number < max_password) {
            // how many passwords need to be generated
            password_per_thread = (max_password - number) / device_count;
            if (password_per_thread > batch_size)
                password_per_thread = batch_size;
    
            pthread_mutex_init(&lock, NULL);
            ThreadArg thread_arg;
    
            for (j = 0; j < device_count; j++) {
                // for (i = 0; i < password_per_thread; i++) {
                //  password.size_bytes = password_len;
                //  sprintf(password.password, pad, password_prefix, number++, password_suffix);
                //  numbers[i] = password;
                // }
                printf("%d\n", j);
                thread_arg.device_params = deviceParams[j];
                printf("A2\n");
                thread_arg.pdf_params = params;
                printf("1\n");
                thread_arg.start = number;
                printf("2\n");
                thread_arg.prefix = password_prefix;
                printf("3\n");
                thread_arg.prefix_length = strlen(password_prefix);
                printf("4\n");
                thread_arg.suffix = password_suffix;
                printf("5\n");
                thread_arg.suffix_length = strlen(password_suffix);
                thread_arg.length = password_len;
                thread_arg.count = password_per_thread;
                printf("6\n");
                pthread_create(&thread_id[j], NULL, runOnThread, &thread_arg);
            }
            void *status;
            for (i = 0; i < device_count; i++) {
                pthread_join(thread_id[i], &status);
                if ((bool *) status) {
                    found = true;
                }
            }
            if (found) {
                break;
            }
        }
    }
    

    SegFault发生在:

    thread_arg.device_params = deviceParams[j];
    

    但如果注释了以下行,则segfault消失:

    pthread_create(&thread_id[j], NULL, runOnThread, &thread_arg);
    

    这是SegFault:

    Thread 2 received signal SIGSEGV, Segmentation fault.
    0x000000010000113b in runCrack () at pdfcrack.c:138
    138                 thread_arg.device_params = deviceParams[j];
    

    这是的输出 gdb bt :

    (gdb) bt
    #0  0x000000010000113b in runCrack () at pdfcrack.c:138
    #1  0x0000000100000bf6 in main (argc=<optimized out>, argv=0x7ffeefbff9c8) at main.c:250
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Erik Alapää    6 年前

    您不应该像这样重用线程参数,这将导致数据争用。请改用这样的arg数组。见

    how not to use the pthread_create arg

    这是一个简单的比赛例子,在我的机器上,它打印2,3,3。

    #include <pthread.h>
    #include <stdexcept>
    #include <iostream>
    
    using std::cout;
    
    const int NR_THREADS = 3;
    pthread_t tid[NR_THREADS];
    
    void* threadfunc(void* arg)
    {
        int val = *(int* )arg;
    
        cout << "Thread got arg " << val << '\n';
    
        return 0;
    }
    
    int main()
    {
        int retval;
    
        for (int i = 0; i < NR_THREADS; i++) {
            retval = pthread_create(&tid[i], NULL, threadfunc, &i);
            if (retval) throw std::runtime_error("Pthread create failed!");
        }
    
        for (int i = 0; i < NR_THREADS; i++) {
            pthread_join(tid[i], NULL);
            if (retval) throw std::runtime_error("Pthread join failed!");
        }
    
        return 0;
    }
    

    这里是避免构建错误所需的差异(还必须更改头位置和ubuntu上的.so lib位置,并删除-framework gcc标志)

    diff pdfcrack/pdfcrack.c pdfcrack_modded/pdfcrack.c
    116c116
    <       pthread_t thread_id = malloc(sizeof(pthread_t) * device_count);
    ---
    >       pthread_t* thread_id = malloc(sizeof(pthread_t) * device_count);
    154c154
    <               pthread_join(&thread_id[i], &status);
    ---
    >               pthread_join(thread_id[i], &status);
    
    推荐文章