【问题标题】:gcc segmentation fault if pthread_create is called如果调用 pthread_create,则 gcc 分段错误
【发布时间】:2018-07-25 08:23:41
【问题描述】:

这段代码好像抛出了segmentation fault,但是如果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;
        }
    }
}

段错误发生在:

thread_arg.device_params = deviceParams[j];

但是如果以下行被注释,则段错误消失:

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

这是段错误:

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

【问题讨论】:

    标签: segmentation-fault pthreads pthread-join


    【解决方案1】:

    你不应该像你一样重用 thread_arg,这会导致数据竞争。请改用此类 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);
    

    【讨论】:

    • 发布一个最小的、完整的示例,SO 用户可以尝试、调试和修改。
    • 这里有一个链接...不能让它变得更小,因为我不确定这里的错误在哪里...drive.google.com/drive/folders/… 完成后,运行它,pdfcrack -d 1 /path/to/a/pdf/file
    • 你检查过 clGetDeviceIDs 的返回吗?你有多少设备?我没有 OpenCL 和可能需要构建的其他依赖项。
    • 是的,这给了我 1 台设备。事实上,这段代码的一个版本直到昨晚都在工作,甚至不确定发生了什么变化!
    • 我现在设法编译并运行您的代码,在答案中添加差异,尝试像我改变的那样改变。我没有要测试的加密 pdf。
    猜你喜欢
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 2018-10-30
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多