我正在尝试实现一个创建线程的类,递增一个值并将其发送到另一个线程,该数字定义为(value * value)%线程数
#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行)时出现分段错误
这就是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
有人能解释一下这个功能究竟发生了什么吗?我该如何正确实现?
非常感谢。
答案 0 :(得分:2)
你func
没有处理NULL
被传入,pthread_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在run
从Worker
转换NULL
时执行了转换和(p=0x0)
的工作。 1}}。请注意(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
counter
工作正常,因为它只能在访问maxval
之前访问m
,Worker::wait()
和#0 0x0000000000400f5a in Worker::wait (this=0x0) at ht19-4.cpp:30
Worker::wait()
在nth
中,您正在访问Worker
,它是null $('#SelectID').change(function(){
$.ajax({
type: "POST",
url: "../example.php",
data: "{selectedvalue: " + $(this).val() + "}",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
success: function(result){
$('#div').html(result);
}
});
});
实例的成员,您最终会获得段错误。
答案 1 :(得分:2)
问题是在创建线程时,您正在为最后一个参数传递NULL
。
pthread_create(&thread, NULL, func, NULL);
线程启动时,会调用 func()
并传递NULL
值。
因此,在 func()
p
内NULL
,您正在尝试投射然后访问该内存位置。这就是你得到分段错误的原因。