【问题标题】:C: pthread segfaultsC: pthread 段错误
【发布时间】:2016-12-26 14:36:24
【问题描述】:

我正在使用 pthread 编写我的第一个 C 程序。我想为命令行 (argv) 上提供的所有(非选项)参数运行我的函数 sha1sum

pthread_t t[256];

c = 0;
for (n = optind; n < argc; n++) {
    if(pthread_create(&t[c], NULL, sha1sum, argv[n])) {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }
    c++;
}

c = 0;
for (n = optind; n < argc; n++) {
    pthread_join(t[c]);
    c++;
}

当使用 2 个命令行参数(file1file2)运行我的程序时。在成功执行 sha1sum 函数后,它有时会立即出现段错误,有时会在最后出现。

有人能指出什么是错的吗?

编辑

事实证明,程序有时仍会出现段错误。有时马上,有时在中间,有时从不:

我在下面发布整个 MCV 示例:

#include <stdio.h>
#include <getopt.h>
#include <unistd.h>
#include <locale.h>
#include <pthread.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <openssl/evp.h>    

static unsigned char flag = 0;


int sha1sum(char *filename) {

    FILE *f;
    size_t len;
    unsigned char buffer[BUFSIZ]; 

    EVP_MD_CTX hashctx;
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    const EVP_MD *hashptr = EVP_get_digestbyname("SHA1");

        f = fopen(filename, "r");

        EVP_MD_CTX_init(&hashctx);
        EVP_DigestInit_ex(&hashctx, hashptr, NULL);

        do {
                len = fread(buffer, 1, BUFSIZ, f);
                EVP_DigestUpdate(&hashctx, buffer, len);
        } while (len == BUFSIZ);

        unsigned int outlen;
        EVP_DigestFinal_ex(&hashctx, buffer, &outlen);
        EVP_MD_CTX_cleanup(&hashctx);

        int i;
        for (i = 0; i < outlen; i++)
                printf("%02x", buffer[i]);

        printf("\n");
        fclose(f);

    pthread_exit(NULL);
}


int main(int argc, char **argv) {

    int c,n;
    pthread_t t[256];

    while ((c = getopt(argc, argv, "c")) != EOF) switch(c) {
        case 'c':
            flag |= 1;
            break;
    }

    c = 0;
    for (n = optind; n < argc; n++) {

        if (pthread_create(&t[c], NULL, &sha1sum, argv[n])) {
            fprintf(stderr, "Error creating thread\n");
            return 1;
        }
        c++;
    }

    c = 0;
    for (n = optind; n < argc; n++) {
        pthread_join(t[c], NULL);
        c++;
    }

    return 0;
}

编辑 2

添加#include &lt;pthread.h&gt; 后,我现在在编译时收到以下错误/警告:

test.c: In function ‘main’:
test.c:67:9: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type [enabled by default]
In file included from test.c:9:0:
/usr/include/pthread.h:225:12: note: expected ‘void * (*)(void *)’ but argument is of type ‘int (*)(char *)’

【问题讨论】:

  • 运行单线程时是否显示相同的行为?
  • 另外请提供MCV example
  • 这个 sn-p 看起来不错,除了 pthread_join 需要 2 个参数(可能需要一个最小的 sha1sum 函数来了解更多信息)。
  • @alk - 当我只使用一个参数(一个文件)运行它时,它不会出现段错误。
  • 编译器告诉你出了什么问题,你的线程函数的类型应该是void* sha1sum(void *arg)(你可以转换成正确的类型)。我还建议您将一些 OpenSSL 的初始化(即OpenSSL_add_all_algorithmsERR_load_crypto_strings)移出线程函数,因为它们可能不是可重入的,并且如果从多个线程并行调用可能会表现不佳。 (或者,使用线程中的pthread_once 来处理这些)

标签: c pthreads


【解决方案1】:

pthread_join(t[c]) 更改为pthread_join(t[c], NULL)

【讨论】:

  • 即使在更正pthread_join 之后,它仍然存在段错误。我已经编辑了我的问题。
【解决方案2】:

我对您的代码做了一些小改动。现在它不会崩溃。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <getopt.h>

void *sha1sum(void) {
    char *a = malloc(10);
    strcpy(a, "hello world\n");
    pthread_exit((void *) a);
}

int main(int argc, char **argv) {
    pthread_t t[256];
    int n = 0;
    int c = 0;
    char *b;
    for (n = optind; n < argc; n++) {
        if (pthread_create(&t[c], NULL, &sha1sum, argv[n])) {
            fprintf(stderr, "Error creating thread\n");
            return 1;
        }
        c++;
    }
    c = 0;
    for (n = optind; n < argc; n++) {
        pthread_join(t[c], (void **) &b);
        printf("b is %s", b);
        c++;
    }
    return 0;
}

测试

./a.out foo bar baz bletch
b is hello world
b is hello world
b is hello world
b is hello world

【讨论】:

  • 这个pthread_join(t[c], (void **) &amp;b);不应该是void * pv; pthread_join(t[c], &amp;pv); b = pv;吗?
  • @Dac Saunders - 谢谢。问题似乎是,我的函数没有pthread_exit
  • 调用pthread_exit() 是不需要的,因为没有什么可以返回的。 @MartinVegter
  • 你的代码的问题是它传递给pthread_join()的几个参数。 @MartinVegter
  • @alk - 我已经更正了pthread_join(),但它仍然存在段错误。我已经编辑了我的问题,并添加了 MCV 示例
猜你喜欢
  • 2011-10-26
  • 2016-04-22
  • 2023-03-31
  • 1970-01-01
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-14
相关资源
最近更新 更多