gpt4 book ai didi

c - 为什么 pthread_join 在最后一次迭代中失败(给出段错误)?

转载 作者:太空宇宙 更新时间:2023-11-04 05:47:28 24 4
gpt4 key购买 nike

这里是多线程初学者。恰好在第 5 次迭代(即执行 pthread_join(threadID[4], NULL) 时),我的程序因段错误而失败。

我正在创建多个线程来从计数器变量中加/减 1 以研究竞争条件。一切顺利,直到我尝试 5 个或更多线程。在 pthread_join(threadID[4], NULL) 的最后一次迭代中,它失败了,我无法确定原因。我确信问题就在那里,因为我使用 printf 语句来查看它在失败之前到达的位置。

#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <time.h>

int opt_threads;
int opt_iterations;
long nThreads;
long nIterations;
int opt_yield;
long long counter;

void add(long long *pointer, long long value) {
long long sum = *pointer + value;
if (opt_yield)
sched_yield();
*pointer = sum;
}

void *thread_worker(void * arg) {
long i;
for (i=0; i<nIterations; i++) {
add(&counter, 1);
add(&counter, -1);
}

return arg;
}

int main(int argc, char *argv[]) {
int c;

pthread_t *threadID = malloc(nThreads * sizeof(pthread_t));
if (threadID == NULL) {
fprintf(stderr, "Thread memory allocation failed\n");
exit(1);
}

static struct option long_options[] =
{
{"threads", required_argument, 0, 't'},
{"iterations", required_argument, 0, 'i'},
{"yield", no_argument, 0, 'y'},
{0,0,0,0}
};

while (1) {
c = getopt_long(argc, argv, "", long_options, NULL);
if (c==-1) break;

switch(c) {
case 't':
opt_threads = 1;
nThreads = atoi(optarg);
break;
case 'i':
opt_iterations = 1;
nIterations = atoi(optarg);
break;

case 'y':
opt_yield = 1;
break;

default:
fprintf(stderr, "Bad argument!\n");
exit(1);
}
}

counter = 0;
struct timespec start, finish;
int i;

//start clock
clock_gettime(CLOCK_MONOTONIC, &start);

//create
for (i=0; i < nThreads; i++) {
pthread_create(&threadID[i], NULL, &thread_worker, NULL);
printf("Created thread[%ld]\n", i);
}

//wait (join)
/*for (i=0; i < nThreads; i++) {
printf("Now i is %ld\n", i);
if (pthread_join(threadID[i], NULL) != 0)
fprintf(stdout,"ERRRRROOOORRRRRRRR\n");

}*/

pthread_join(threadID[0], NULL);
pthread_join(threadID[1], NULL);
pthread_join(threadID[2], NULL);
pthread_join(threadID[3], NULL);
pthread_join(threadID[4], NULL);

printf("about to end clock\n");
//finish clock
clock_gettime(CLOCK_MONOTONIC, &finish);

printf("finished clock\n");

long seconds = finish.tv_sec - start.tv_sec;
long ns = finish.tv_nsec - start.tv_nsec;
long runTime = (seconds + ns) * 1000000000L;
long nOperations = nThreads * nIterations * 2;
long avgOperations = runTime / nOperations;
long run_time = 1000000000L * (finish.tv_sec - start.tv_sec) + finish.tv_nsec - start.tv_nsec;

//Print
if (opt_yield == 0)
fprintf(stdout, "add-none, %ld, %ld, %lld, %ld, %lld, %lld\n", nThreads, nIterations, nOperations, run_time, run_time/nOperations, counter);

else if (opt_yield == 1)
fprintf(stdout, "add-yield-none, %ld, %ld, %lld, %ld, %lld, %lld\n",nThreads, nIterations, nOperations, run_time, run_time/nOperations, counter);

exit(0);
}

我希望程序能够正确等待第 5 个线程,但由于段错误而失败。

最佳答案

您的 main 函数开始:

int main(int argc, char *argv[])
{
int c;

pthread_t *threadID = malloc(nThreads * sizeof(pthread_t));

因为 nThreads 是一个没有显式初始化器的全局变量,它的值为零——您还没有分配任何可以合法使用的内存。访问该内存会导致未定义的行为。

将内存分配推迟到您知道需要多少线程之后。

未定义的行为意味着任何事情都可能发生,包括看似有效直到它不再有效。

您还需要将线程加入代码重写为一个循环,以匹配创建线程的循环。

关于c - 为什么 pthread_join 在最后一次迭代中失败(给出段错误)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57350633/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com