【问题标题】:Segmentation fault when creating a thread创建线程时出现分段错误
【发布时间】:2015-12-18 16:48:43
【问题描述】:

我正在尝试实现一个类,该类创建一个线程,递增一个值并将其发送到另一个线程,该数字定义为(值 * 值)% 线程数

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdlib>
#include <vector>

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
volatile int counter = 0;
volatile int maxval = 0;
volatile int next = 0;

extern "C" void *func(void *p);

class Worker {
private:
    pthread_t thread = 0;
    int nth = 0;
    int nproc = 0;
public:
    Worker () {};
    Worker(int _nproc, int _nth) {
        nth = _nth;
        nproc = _nproc;
    };
    void start() {
        pthread_create(&thread, NULL, func, NULL); // Line 27

    };
    void wait() {
        while (nth != next) {
            pthread_cond_wait(&cv, &m);
        }
    };
    void notify() {
        pthread_cond_broadcast(&cv);
    };
    void run() {
        while (counter != maxval) {
            pthread_mutex_lock(&m);
            Worker::wait();
            if (counter != maxval) {
                printf("%d %d\n", nth, counter);
                ++counter;
            }
            next = (counter * counter) % nproc;
            Worker::notify();
            pthread_mutex_unlock(&m);
        }
    };
    void join() {
        pthread_join(thread, NULL);
    }
};

extern "C" void *func(void *p) {
    Worker *w = reinterpret_cast<Worker*>(p);
    w->run();
    return NULL;
}

int main(int argc, char *argv[]) {
    int nthreads = atoi(argv[1]);
    maxval = atoi(argv[2]);
    std::vector<Worker> workers;
    for (int i = 0; i != nthreads; ++i) {
        workers.push_back(Worker(nthreads, i));
    }
    for (int i = 0; i != workers.size(); ++i) {
        workers[i].start();
    }
    for (int i = 0; i != workers.size(); ++i) {
        workers[i].join();
    }
    return 0;
}

无法检查算法是否正确,因为我在调用 pthread_create(第 27 行)时遇到 Segmentation Error(第 27 行)

gdb 是这么说的:

#0  0x0000000000400f5a in Worker::wait (this=0x0) at ht19-4.cpp:30
#1  0x0000000000400fd5 in Worker::run (this=0x0) at ht19-4.cpp:40
#2  0x0000000000400d26 in func (p=0x0) at ht19-4.cpp:57
#3  0x00007ffff76296aa in start_thread (arg=0x7ffff6f4f700)
    at pthread_create.c:333
#4  0x00007ffff735eeed in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

谁能解释一下这个函数到底发生了什么?如何正确实施?

非常感谢。

【问题讨论】:

  • @EliasVanOotegem 我认为它在主要之上。
  • 根据您的堆栈跟踪,您的崩溃似乎在 func() 正在调用的东西中。条目Worker::run (this=0x0) 表明您有一个未初始化的对象指针;你是怎么初始化的?
  • 很高兴在 C++ 问题中看到一些 gdb。 :)
  • 让专家完成繁重的工作。使用std::thread

标签: c++ multithreading pthreads thread-synchronization


【解决方案1】:

您的 func 无法处理传入的 NULLpthread_create 的第四个参数是在第三个参数中发送给函数的内容。

更改func 以正确处理NULL,您应该会很好:

extern "C" void *func(void *p) {
    if (NULL == p)
        return NULL;
    Worker *w = reinterpret_cast<Worker*>(p);
    w->run();
    return NULL;
}

另外,+1 用于发布 gdb 输出,所以这里有更多信息:

如果我们向上跟踪您的堆栈跟踪(我按它们发生的顺序键入它们),我们会看到 func 在它从NULL 投射的Worker 上完成了转换和调用run 的工作。注意(p=0x0)(this=0x0)

#2  0x0000000000400d26 in func (p=0x0) at ht19-4.cpp:57
#1  0x0000000000400fd5 in Worker::run (this=0x0) at ht19-4.cpp:40

Worker::run 工作正常,因为它只访问countermaxvalm,然后才能访问Worker::wait()

#0  0x0000000000400f5a in Worker::wait (this=0x0) at ht19-4.cpp:30

Worker::wait() 中,您正在访问nth,它是空Worker 实例的成员,您最终得到了段错误。

【讨论】:

  • 是的,这样就行了!
【解决方案2】:

问题是在创建线程时,您将 NULL 传递给最后一个参数。

pthread_create(&thread, NULL, func, NULL);

当线程启动时,它会调用 func() 并将 NULL 值传递给它。 所以在 func() p 内部是 NULL 并且您正在尝试转换然后访问该内存位置。这就是您遇到分段错误的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 2017-03-17
    • 2014-12-12
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多