再次使用 pthreads:为什么我的线程函数中的 for 循环会产生溢出?
pthreads again: why does the for-loop inside my thread function generate overflow?
我使用 4 个线程,我的代码让 4 个线程处理 10000 个整数的 1/4 四分之一,并找到该四分之一的所有质数。
(我知道这不是一个很顺利的解决方案...)
{
...
for (int o{my_data->thread_id*2500}; o < (my_data->thread_id *2500) +2500; o++){
if (prime(o) == true)
ss << o << "\n" ;
}
...
}
现在,当我尝试将其用于 100000 个整数时,出现溢出:
threads.cpp:46:68: runtime error: signed integer overflow: 1103437824 * 25000 cannot be represented in type 'int'
我不明白。因为数字“1103437824”不应该是 0、1、2 或 3?
我的代码:
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <math.h>
#include <sstream>
#define NUM_THREADS 4
using namespace std;
bool prime(int n)
{
if (n == 1) { return false; };
if ((n == 2) || (n == 3)) { return true; };
if ((n % 2 == 0 ) || (n % 3 == 0)) { return false; };
int sqrt_n{ 0 };
sqrt_n = sqrt(n);
int i{ 5 };
while (i <= sqrt_n) {
if (n % i == 0) return false;
i += 2;
}
return true;
}
struct thread_data {
int thread_id;
int number;
};
void *worker(void *threadarg) {
struct thread_data *my_data;
my_data = (struct thread_data *) threadarg;
std::stringstream ss;
ss << "Thread ID : " << my_data->thread_id << "\n";
for (int o{my_data->thread_id*25000}; o < (my_data->thread_id *25000) +25000; o++){
if (prime(o) == true)
ss << o << "\n" ;
}
std::cout << ss.str ();
pthread_exit(NULL);
}
int main () {
pthread_t threads[NUM_THREADS];
struct thread_data t_d[NUM_THREADS];
int rr;
int i;
for( i = 0; i < NUM_THREADS; i++ ) {
t_d[i].thread_id = i;
rr = pthread_create(&threads[i], NULL, worker, (void *)&t_d[i]);
if (rr) {
cout << "Error:unable to create thread," << rr << endl;
exit(-1);
}
}
pthread_exit(NULL);
}```
根据该错误消息,my_data->thread_id
似乎没有介于 0
和 NUM_THREADS - 1
之间的值。它似乎具有 1103437824
的值。这可能是因为 my_data
变成了 dangling pointer, due to a race conditon.
my_data
指向主线程中的 t_d
数组。但是,一旦主线程调用 pthread_exit
,该对象的生命周期就结束了。因此,发生这种情况后,其他线程的 my_data
指针变为悬空,这意味着它不再指向有效对象。取消引用此类指针会导致未定义的行为。
最好的解决方案可能是主线程在所有工作线程上调用 pthread_join
,然后再从函数 main
调用 returns 或调用 pthread_exit
。这样,可以保证主线程的 t_d
数组的生命周期超过工作线程的 my_data
指针的生命周期,因此这些指针永远不会悬空。
我使用 4 个线程,我的代码让 4 个线程处理 10000 个整数的 1/4 四分之一,并找到该四分之一的所有质数。 (我知道这不是一个很顺利的解决方案...)
{
...
for (int o{my_data->thread_id*2500}; o < (my_data->thread_id *2500) +2500; o++){
if (prime(o) == true)
ss << o << "\n" ;
}
...
}
现在,当我尝试将其用于 100000 个整数时,出现溢出:
threads.cpp:46:68: runtime error: signed integer overflow: 1103437824 * 25000 cannot be represented in type 'int'
我不明白。因为数字“1103437824”不应该是 0、1、2 或 3?
我的代码:
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <math.h>
#include <sstream>
#define NUM_THREADS 4
using namespace std;
bool prime(int n)
{
if (n == 1) { return false; };
if ((n == 2) || (n == 3)) { return true; };
if ((n % 2 == 0 ) || (n % 3 == 0)) { return false; };
int sqrt_n{ 0 };
sqrt_n = sqrt(n);
int i{ 5 };
while (i <= sqrt_n) {
if (n % i == 0) return false;
i += 2;
}
return true;
}
struct thread_data {
int thread_id;
int number;
};
void *worker(void *threadarg) {
struct thread_data *my_data;
my_data = (struct thread_data *) threadarg;
std::stringstream ss;
ss << "Thread ID : " << my_data->thread_id << "\n";
for (int o{my_data->thread_id*25000}; o < (my_data->thread_id *25000) +25000; o++){
if (prime(o) == true)
ss << o << "\n" ;
}
std::cout << ss.str ();
pthread_exit(NULL);
}
int main () {
pthread_t threads[NUM_THREADS];
struct thread_data t_d[NUM_THREADS];
int rr;
int i;
for( i = 0; i < NUM_THREADS; i++ ) {
t_d[i].thread_id = i;
rr = pthread_create(&threads[i], NULL, worker, (void *)&t_d[i]);
if (rr) {
cout << "Error:unable to create thread," << rr << endl;
exit(-1);
}
}
pthread_exit(NULL);
}```
根据该错误消息,my_data->thread_id
似乎没有介于 0
和 NUM_THREADS - 1
之间的值。它似乎具有 1103437824
的值。这可能是因为 my_data
变成了 dangling pointer, due to a race conditon.
my_data
指向主线程中的 t_d
数组。但是,一旦主线程调用 pthread_exit
,该对象的生命周期就结束了。因此,发生这种情况后,其他线程的 my_data
指针变为悬空,这意味着它不再指向有效对象。取消引用此类指针会导致未定义的行为。
最好的解决方案可能是主线程在所有工作线程上调用 pthread_join
,然后再从函数 main
调用 returns 或调用 pthread_exit
。这样,可以保证主线程的 t_d
数组的生命周期超过工作线程的 my_data
指针的生命周期,因此这些指针永远不会悬空。