c - pthread_cancel 后出现段错误

标签 c multithreading segmentation-fault pthreads

在我的程序中,我有两个线程,一个计算一些递归函数,另一个在第一个线程进行计算时显示“进度点”。有代码:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#define test_errno(msg) do{if (errno) {perror(msg); exit(EXIT_FAILURE);}} while(0)

void *progressDotsThread(void* _arg){
    for(int i=0;;i++){
    printf(".");
    fflush(stdout);
    sleep(1);
    }
}
void *seriesCalculateThread(void* n){
    int result;

    if((long)n==1) return (void*)(1);
    else if((long)n==2) return (void*)(-5);
    else{
         int nmin1 = (long)seriesCalculateThread( (void*) ( (long)n -1   ));
         int nmin2 = (long)seriesCalculateThread( (void*) ( (long)n -2   ));
         result = nmin1*((long)n)*nmin2;
         return (void*)(result);
    }
}

int main(void) {
    long n=0;
    int result =0;
    pthread_t w1,w2;

    printf("Give n\n");
    scanf ("%d",&n);

    if(n<1){
        printf("Value must be higher than 0");
    }
    else{

        errno= pthread_create(&w2,NULL,seriesCalculateThread,(void *)n);
        test_errno("pthread_create");
        errno= pthread_create(&w1,NULL,progressDotsThread,NULL);
        test_errno("pthread_create");

        if(!pthread_join(w2,(void**)&result)){
            errno = pthread_cancel(w1); //<--- Where segmentation fault happens
            test_errno("pthread_cancel");
        }
        printf("%d\n", result);

    }

    return EXIT_SUCCESS;
}

pthread_create 它们两个,然后我 if(!pthread_join) 执行计算的那个,当计算完成时我取消显示点的那个。

if(!pthread_join(w2,(void**)&result)){
                errno = pthread_cancel(w1); //<--- Where segmentation fault happens
                test_errno("pthread_cancel");
            }

虽然我在调用 pthread_cancel(w1) 后遇到段错误,但我还是这样做了,我不知道为什么会这样。

我尝试使用 gcc -g -Wall -pthread psthreadss.c -lpthread 编译它的终端,但它没有在 eclipse 中那样好用。如果相关,我会使用 Ubuntu 18.04。

最佳答案

and then I if(!pthread_join) the one that does calculations and when calculations finish I cancel the one that display dots.

您的程序存在逻辑错误和内存损坏错误。

逻辑错误:您假设 !pthread_join 意味着计算完成。 不是那个意思。 pthread_join 返回非零状态 如果您使用不正确的参数调用它(线程 ID w2 未知、尚未启动或已已经加入)。

您的代码应该看起来像这样:

int rc = pthread_join(w2, ...);
assert(rc == 0);
rc = pthread_cancel(w1);
assert (rc == 0);

关于内存损坏错误:在 64 位系统(我假设您正在使用的系统)上,sizeof(int) == sizeof(result) == 4,但是 sizeof(void*) == 8

这段代码:

 int result =0;
 ...
    pthread_join(w1, (void**)&result)

获取一个 4 字节的 result 地址,并要求 pthread_join 将一个 8 字节的值存储在那里。可预见的结果是堆栈损坏。

我不知道这究竟是如何触发 SIGSEGV 的,但是一旦您的程序中出现未定义的行为,所有的赌注都会被取消。

要解决此问题,请将 result 类型更改为 intptr_t。我希望在该修复后崩溃会消失。

在进行任何更改之前,您还应该尝试使用 Address Sanitizer:gcc -fsanitize=address -g ...。它很有可能会告诉您有关堆栈溢出的信息。

关于c - pthread_cancel 后出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53357836/

相关文章:

c++ - 实现文件锁以复制文件

python - 多线程应用程序中的 _wait_for_tstate_lock 错误

c++ - 多线程 C++ Qt 应用程序仅在 VS 调试器中出现奇怪的运行时错误

c - 使用指针遍历数组时出现段错误

c - 为什么这个程序没有段错误?

c - C 中结构的内存错误

c - 如何使用环绕查找 C 中字符之间的距离

c# - 发送大量数据时“连接被远程主机强行关闭”

C strcpy() 复制字符串文字而没有段错误

c - 想了解更多警告 : comparison between pointer and integer in C programming