遵循本教程: https://www.pluralsight.com/courses/linux-network-programming 我发现了非常有趣的行为,请检查以下代码:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void *func(void *arg)
{
pthread_exit((void *)99);
}
int main()
{
pthread_t handle;
int exitcode;
int i = 0;
int y = 5;
while (1) {
y++;
// i++;
printf("primary thread: y == %d\n", y);
pthread_create(&handle, NULL, func, "hi!");
pthread_join(handle, (void **)&exitcode);
sleep(1);
}
}
//gcc -o t failtesting.c -O0 -l pthread ; ./t
//primary thread: y == 6
//primary thread: y == 1
//primary thread: y == 1
//^C
以某种方式加入子线程将变量y重置为0,为什么会发生?
最奇怪的部分是:如果你取消注释i ++,一切都会恢复正常:
gcc -o t failtesting.c -O0 -l pthread ; ./t
primary thread: y == 5
primary thread: y == 6
primary thread: y == 7
primary thread: y == 8
答案 0 :(得分:3)
这......
int exitcode;
[...]
pthread_join(handle, (void **)&exitcode);
...产生未定义的行为,因为&exitcode
的引用是int
,但pthread_join
会导致将值写入void *
}。
对于未定义的行为而言,这是完全足够的,无论其他任何考虑因素如何。但是,在考虑为什么 C可能会将此类情况声明为UB时,请考虑void *
的大小大于{{1}的大小是很常见的当程序试图将数据写入太小的空间时,应该发生什么呢?
最奇怪的部分是:如果你取消注释i ++,一切都会恢复正常
这种异常表明您的计划正在展示UB。 C标准明确否认有任何解释 - 这是什么&#34;未定义的行为&#34;装置
无论如何,看起来你想要这个,而不是:
int
准备让编译器发出一个关于指针到int转换的合理的警告,尽管你应该能够通过转换为 void *exit_ptr;
pthread_join(handle, &exit_ptr);
exitcode = (int) exit_ptr;
来沉默它。