64位Windows下strcpy()返回值读字符串报访问违规问题
问题表现
打印strcpy()返回值时程序触发*Access violation reading location(读取位置访问冲突)*异常,初始测试代码如下:
char ind[15]; printf("%s\n", strcpy(ind, "source text"));
添加调试语句后的代码:
char* ins = "source text"; char* dst; dst = strcpy(ind, ins); printf("dst = %s", dst);
Visual Studio调试器观测结果:
ind地址为0x00000024ec71f448,可正确指向字符串"source text"dst地址为0xffffffffec71f448,调试器提示Error reading characters of string(读取字符串字符失败)、Unable to read memory(无法读取内存)
按照strcpy()的函数定义,dst应当与ind相等、指向同一内存地址,该异常表现不符合函数预期行为。
根因定位
排查后确认问题由两点共同导致:
- 未包含
<string.h>头文件时,编译器会对strcpy()采用隐式声明,默认将其识别为返回int类型的函数;只有正确引入对应头文件后,编译器才会匹配正确的函数签名,将其识别为返回char*类型的函数。 - 运行环境为64位Windows 10,64位平台下
int类型通常为32位长度,而指针类型为64位长度,类型不匹配导致strcpy()返回的指针值被截断为32位,高32位为非法填充值,最终生成不可访问的非法内存地址。
VS环境编译适配说明
在Visual Studio中编译使用strcpy()的代码时,需要在所有头文件引入前添加#define _CRT_SECURE_NO_WARNINGS避免编译报错:VS默认会提示使用安全版本strcpy_s()替代原生strcpy(),而strcpy_s()执行成功时返回值为0,直接将其返回值赋值给char*类型的dst会得到NULL指针,添加上述宏定义即可跳过该安全限制,正常使用原生strcpy()。
完成上述修复后重新编译运行,dst与ind地址完全一致,均可正确指向目标字符串,访问冲突异常不再触发。
内容的提问来源于stack exchange,提问作者Leon Chang
相关产品推荐
相关产品推荐

