int指针转size_t指针在64位环境崩溃的原因及迁移注意事项
#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中崩溃。将int var = 10;修改为size_t var = 10;后问题解决,针对此场景的问题解答如下:
1. 将小数据长度类型(如int)的指针转换为大数据长度类型(如long/size_t)是否错误?
是,这种操作属于未定义行为,严格来说是错误的。C标准规定,将指向小内存宽度类型的指针强制转换为大宽度类型指针后,通过该指针访问原变量会越界读写,违反类型别名规则,同时破坏内存布局。
2. 此场景下导致崩溃的原因是什么?
64位环境中size_t为8字节,而int通常是4字节。当func函数执行*ptr = len;时,会尝试向ptr指向的地址写入8字节数据,但原变量var仅占用4字节内存,这会触发越界写入,覆盖var相邻的内存区域。如果相邻内存是栈帧的关键数据(如返回地址、栈指针)或其他变量,会直接破坏程序的执行环境,最终引发核心转储或崩溃。
不同在线编译器的表现差异,源于它们的栈布局、内存保护机制不同:部分环境中var相邻内存未被使用或未受保护,因此不会立刻崩溃;而programiz的环境可能对栈内存有严格的边界检查,越界写入直接触发崩溃。
3. 迁移至64位环境时,指针相关还有哪些注意事项?
- 禁止随意进行不同宽度类型的指针转换,尤其是小类型转大类型的指针,必须确保原变量的内存大小能容纳目标类型的数据。
- 统一使用匹配类型:用
size_t表示内存长度、数组索引时,对应的变量和指针也应使用size_t,避免混用int。 - 注意指针本身的宽度:64位环境下指针是8字节,不要用
int存储指针值(如int ptr_val = (int)&var;),这会导致截断,正确做法是用uintptr_t或intptr_t存储指针的整数形式。 - 检查格式化字符串:
printf中打印指针必须用%p,打印size_t类型要用%zu格式符,否则会因类型不匹配导致输出错误或行为异常。 - 警惕栈溢出:64位环境下栈的默认大小可能与32位不同,大量使用栈上大变量时需注意内存占用。
内容的提问来源于stack exchange,提问作者RandomGuy
相关产品推荐
相关产品推荐

