我有以下代码。
#include<stdio.h>
void func(size_t *ptr)
{
printf("Before *ptr = %d &ptr = %p\n",*ptr, &ptr);
unsigned int len = 100;
*ptr = len;
printf("After *ptr = %d &ptr = %p\n",*ptr, &ptr);
}
void main()
{
int var = 10;
printf("Before var = %d &var = %p\n",var, &var);
func((size_t *)&var);
printf("After var = %d &var = %p\n",var, &var);
return;
}
这段代码在32位环境中运行良好。我正在将应用程序迁移到64位,在这种情况下,代码会生成一个核心转储。它在一些在线编译器中运行良好,如代码codepad.org,但在programiz中崩溃。
我知道在64位环境中size_t size是8字节,但在32位环境中是4字节,所以我设法通过修改下面的行来解决这个问题。
size_t var = 10;
所以我的问题是,将一个较小数据大小的指针(例如int)赋给较大数据大小的指针(例如long/size_t)是错误的吗?
在这种情况下,是什么导致了这个问题?
在迁移到64位环境时,我还应该注意哪些与指针相关的事情?
3条答案
按热度按时间r1wp621o1#
在我的系统上,
sizeof(size_t)
大于sizeof(int)
。在你的函数中,你可以从指针传递的
int
变量之外的内存中读写数据,你可以访问没有分配给你的变量的内存,并调用Undefined Behaviour(UB)。zaqlnxep2#
以下内容不正确:
func
将访问var
的内存,就好像它是size_t
一样,但它不是。这会导致未定义的行为。应该是
注:
1.这里假设
var
的值可以用size_t
表示,如果不能,“通过在新类型中可以表示的最大值的基础上反复加1或减1来转换该值,直到该值在新类型的范围内。”1.这里假设
tmp
的值可以用int
表示,如果不能,“要么结果是实现定义的,要么产生实现定义的信号”。but5z9lq3#
当ptr指针传递给func时(),它将被强制转换为size_t*。但是,&ptr仍然是指向size_t* 的指针,而不是指向int的指针(这就是var的含义)。在32位环境中,sizeof(size_t*)是4个字节,因此当打印&ptr时,它会打印正确的值。(size_t*)是8个字节,因此当打印&ptr时,它打印错误的值,导致printf()函数读取ptr变量边界之外的内存,从而导致未定义的行为和潜在的崩溃。