C语言 使用int变量分配size_t时发生崩溃

hs1rzwqc  于 2023-03-17  发布在  其他
关注(0)|答案(3)|浏览(144)

我有以下代码。

#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位环境时,我还应该注意哪些与指针相关的事情?

r1wp621o

r1wp621o1#

int main(void)
{
    printf("sizeof(size_t) = %zu , sizeof(int) = %zu\n", sizeof(size_t), sizeof(int));
}

在我的系统上,sizeof(size_t)大于sizeof(int)
在你的函数中,你可以从指针传递的int变量之外的内存中读写数据,你可以访问没有分配给你的变量的内存,并调用Undefined Behaviour(UB)。

zaqlnxep

zaqlnxep2#

以下内容不正确:

int var = 10; 

func( (size_t *)&var );

func将访问var的内存,就好像它是size_t一样,但它不是。这会导致未定义的行为。
应该是

int var = 10;

size_t tmp = var;  // See note 1.
func( &tmp );
var = tmp;         // See note 2.

注:
1.这里假设var的值可以用size_t表示,如果不能,“通过在新类型中可以表示的最大值的基础上反复加1或减1来转换该值,直到该值在新类型的范围内。”
1.这里假设tmp的值可以用int表示,如果不能,“要么结果是实现定义的,要么产生实现定义的信号”。

but5z9lq

but5z9lq3#

当ptr指针传递给func时(),它将被强制转换为size_t*。但是,&ptr仍然是指向size_t* 的指针,而不是指向int的指针(这就是var的含义)。在32位环境中,sizeof(size_t*)是4个字节,因此当打印&ptr时,它会打印正确的值。(size_t*)是8个字节,因此当打印&ptr时,它打印错误的值,导致printf()函数读取ptr变量边界之外的内存,从而导致未定义的行为和潜在的崩溃。

相关问题