洗掉 printf 陳述句會影響程式創建子執行緒的回圈中“i”的值。我試過列印一個非格式化的字串,它破壞了程式。將 printf 移到 pthread_create() 上方會導致相同的結果。但是,在創建執行緒后列印任何格式化字串將“修復”程式。有誰知道我做錯了什么?
#include <stdio.h>
#include <pthread.h>
#define FALSE 0
#define TRUE !FALSE
pthread_mutex_t mutex;
pthread_cond_t cond1;
pthread_cond_t cond2;
int flag1 = FALSE;
int flag2 = FALSE;
void* someFunction(void* arg);
void anotherFunction(int threadNumber);
int main(int argc, char* argv[])
{
pthread_t threads[6];
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond1, NULL);
pthread_cond_init(&cond2, NULL);
for (int i = 0; i < 6; i )
{
// moving the printf to here will cause the program to hang
pthread_create(&threads[i], NULL, &someFunction, &i);
// not printing a formatted string here will cause the program to hang
printf("Thread %d created\n", i);
}
pthread_mutex_lock(&mutex);
for (int i = 0; i < 6; i )
{
flag1 = TRUE;
// go to child thread
pthread_cond_signal(&cond1);
// wait for child thread to change flag2
while (flag2 == FALSE)
{
pthread_cond_wait(&cond2, &mutex);
}
flag2 = FALSE;
pthread_mutex_unlock(&mutex);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond1);
pthread_cond_destroy(&cond2);
return 0;
}
void* someFunction(void* arg)
{
int threadNumber = *(int*)arg;
pthread_mutex_lock(&mutex);
// wait for parent thread to change flag1
while (flag1 == FALSE)
{
pthread_cond_wait(&cond1, &mutex);
}
anotherFunction(threadNumber);
flag2 = TRUE;
// go back to parent thread
pthread_cond_signal(&cond2);
pthread_mutex_unlock(&mutex);
return NULL;
}
void anotherFunction(int threadNumber)
{
if (threadNumber == 0)
{
printf("I'm thread %d!\n", threadNumber);
}
else if (threadNumber == 1)
{
printf("I'm thread %d!\n", threadNumber);
}
else if (threadNumber == 2)
{
printf("I'm thread %d!\n", threadNumber);
}
else if (threadNumber == 3)
{
printf("I'm thread %d!\n", threadNumber);
}
else if (threadNumber == 4)
{
printf("I'm thread %d!\n", threadNumber);
}
else if (threadNumber == 5)
{
printf("I'm thread %d!\n", threadNumber);
}
}
這是列印格式化字串時的輸出。
Thread 0 created
Thread 1 created
Thread 2 created
Thread 3 created
Thread 4 created
Thread 5 created
I'm thread 0!
I'm thread 1!
I'm thread 2!
I'm thread 3!
I'm thread 4!
I'm thread 5!
這是洗掉 printf 時的輸出
I'm thread 1!
I'm thread 2!
I'm thread 3!
I'm thread 4!
I'm thread 5!
該程式在列印“我是執行緒 5!”后掛起。
編輯:謝謝大家的回復!這是解決方案
for (int i = 0; i < 6; i )
{
int* copy = malloc(sizeof(int));
*copy = i;
// moving the printf to here will cause the program to hang
pthread_create(&threads[i], NULL, &someFunction, copy);
// not printing a formatted string here will cause the program to hang
printf("Thread %d created\n", i);
}
uj5u.com熱心網友回復:
在這里,您將區域變數的地址傳遞i給執行緒函式。至少在for回圈結束時(或者甚至可能在每次迭代結束時),這個變數會超出范圍。這意味著回圈結束后(或回圈迭代結束后)執行緒對變數的每次訪問都是未定義的行為。
for (int i = 0; i < 6; i )
{
// moving the printf to here will cause the program to hang
pthread_create(&threads[i], NULL, &someFunction, &i);
// not printing a formatted string here will cause the program to hang
// printf("Thread %d created\n", i);
}
當您使用 GCC 使用 options 編譯程式時,您的程式將報告此錯誤-fsanitize=address -fsanitize=undefined。
即使您修復了變數的范圍,例如通過將其移動到 functionmain的范圍,您將相同變數的地址傳遞給所有執行緒,因此每個執行緒可以看到哪個值 (0..6) 是未定義的。如果執行緒創建比實際啟動執行緒快,則所有執行緒可能會看到相同的值 6。
uj5u.com熱心網友回復:
謝謝大家的回復!解決方案是動態分配一些記憶體來復制i
for (int i = 0; i < 6; i )
{
int* copy = malloc(sizeof(int));
*copy = i;
// moving the printf to here will cause the program to hang
pthread_create(&threads[i], NULL, &someFunction, copy);
// not printing a formatted string here will cause the program to hang
printf("Thread %d created\n", i);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/475215.html
