c - Pthreads而不是共享变量
问题描述
在学习本教程时: 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
解决方案
这 ...
int exitcode;
[...]
pthread_join(handle, (void **)&exitcode);
... 产生未定义的行为,因为引用的&exitcode
是 a int
,但pthread_join
会导致将值写入它,就好像它是 a 一样void *
。
无论任何其他考虑如何,这本身就足以使行为未定义。但是,在考虑为什么void *
C 可能将这种情况声明为 UB 时,请考虑 a 的大小大于a 的大小是很常见的int
,所以当程序尝试将数据写入 a 时应该发生什么空间太小了?
最奇怪的部分是:如果你取消注释 i++,一切都会恢复正常
诸如此类的异常表明您的程序正在展示 UB。C 标准明确否认对此有任何解释——这是“未定义行为”含义的一部分。
无论如何,看起来你想要这个,而不是:
void *exit_ptr;
pthread_join(handle, &exit_ptr);
exitcode = (int) exit_ptr;
准备好让编译器发出关于指向 int 的指针转换的合理警告,尽管您应该能够通过转换为 来消除它intptr_t
。
推荐阅读
- firebase-realtime-database - Firebase 实时数据库规则中的这个值指的是哪里?
- python - 实现解析梯度
- python - 为什么 GNU 科学库矩阵乘法比 numpy.matmul 慢?
- python - 快速问题:在实践中使用 tfds.load 中的 shuffle_files 改组数据
- python - Python - 如何将整数加密为字母?
- r - 如何使用 dplyr 包在 R 中使用连接的数据库?
- python - Python - “NoneType”对象不可下标?
- java - 我尝试了所有解决方案,但它不起作用。在以下任何来源中都找不到插件 [id: 'com.google.gms.google-services']
- javascript - jquery验证工作,但fform没有被发布
- java - Spring JPA 存储库查询更新卡住/阻塞