为何执行ft_strcpy后指针src及指向的数组c被修改?
问题分析:ft_strcpy执行后源数组被意外修改的原因
现象描述
执行dest = ft_strcpy(dest, src)后,指针src指向的数组c被修改,输出开头出现垃圾值;但直接通过write(1, ft_strcpy(dest, src), 10)打印函数结果时一切正常。经测试,当dest指向的数组c2长度小于c的长度+1时,就会触发源数组被修改的问题。
复现代码
char *ft_strcpy(char *dest, char *src) { char *ptr1; char *ptr2; ptr1 = src; ptr2 = dest; while (*src != '\0') { *dest = *src; src++; dest++; } *dest = '\0'; src = ptr1; dest = ptr2; return (dest); } int main (void) { char c[10] = "Hola Pepe "; char c2[10]; char *src, *dest; src = c; dest = c2; write(1, src, 10); write(1, "\n", 1); write(1, dest, 10); write(1, "\n", 1); dest = ft_strcpy(dest, src); write(1, "----------\n", 11); write(1, src, 10); write(1, "\n", 1); write(1, dest, 10); //write(1, ft_strcpy(dest, src), 10); }
问题根源
核心原因是缓冲区溢出(数组越界写入),破坏了相邻内存区域的数据:
- 源数组
c[10]初始化的字符串"Hola Pepe "刚好占满10个字节,编译器无法自动添加字符串终止符\0。这导致ft_strcpy中的while (*src != '\0')循环无法正常终止,会持续读取src指向的内存,直到找到某个\0为止。 - 目标数组
c2[10]长度同样为10,当ft_strcpy向c2写入10个字节后,会继续向c2之外的内存区域写入数据。由于栈上变量的布局特性,c数组很可能紧邻c2的内存区域,溢出的写入操作直接覆盖了c数组的内容,导致后续读取src时出现垃圾值。 - 直接调用
write(1, ft_strcpy(dest, src), 10)时,write仅读取前10个字节就停止,此时c数组还未被完全覆盖,因此看起来结果正常;但执行赋值操作后再打印src,c已经被溢出数据破坏,就会显示垃圾值。
另外,ft_strcpy中的src = ptr1; dest = ptr2;属于冗余代码——函数参数是传值传递,修改函数内的src和dest副本不会影响外部指针,对逻辑无实际作用。
解决方案
- 确保源字符串有终止符:将源数组
c的长度改为11,让编译器能在字符串末尾自动添加\0,比如:char c[11] = "Hola Pepe "; - 保证目标缓冲区足够大:目标数组
c2的长度必须能容纳源字符串的全部内容(包括\0),避免越界写入。如果源字符串长度为10(含\0),c2至少需要11个字节的空间。 - 可选:添加边界检查:如果需要更安全的实现,可以在
ft_strcpy中加入目标缓冲区长度的参数,限制复制的字节数,避免无限制的越界写入。
内容的提问来源于stack exchange,提问作者NachoK66
相关产品推荐
相关产品推荐

