使用pipe()函数时字符指针全局与局部声明的输出差异问题
全局vs局部字符串指针导致管道输出垃圾值的原因分析
咱们先拆解下问题里的核心现象:同样的管道读写逻辑,把字符串指针msg1、msg2从全局移到局部后,输出就出现了垃圾值。其实这个锅根本不在全局/局部指针本身,而是printf的%s格式符和内存布局的巧合在搞事情!
核心问题出在字符串终止符
先看代码里的细节:
- 你用
write(file[1], msg1, 6)写了6个字节,而"HELLLO"这个字符串字面量本身是7个字节(6个字符+末尾的\0),但你只写了前6个——也就是说,管道里的数据是没有\0终止符的。 - 读数据的
buf是char buf[6],刚好装下6个字节,读完后buf里同样没有\0。
而printf("%s", buf)的规则是:从buf的起始地址开始输出字符,直到遇到\0才会停止。这就意味着,它会越界读取buf后面的内存内容,直到碰到第一个\0为止。
全局/局部变量为啥会影响结果?
这就涉及到C程序的内存布局了:
- 当
msg1、msg2是全局变量时,它们会被存在静态存储区。而main里的buf在栈上,这时候栈里buf后面的内存区域,刚好可能是栈帧里的某个初始化为0的变量(比如返回地址附近的填充字节),所以printf越界读的时候刚好很快碰到\0,输出看起来就正常。 - 当把
msg1、msg2改成局部变量后,它们会被存在栈上,放在buf的某个位置(具体取决于编译器的栈布局)。这时候buf后面的内存是栈里的旧数据(垃圾值),没有现成的\0,printf就会一直输出这些垃圾内容,直到在某个随机位置碰到\0为止。
怎么解决这个问题?
其实很简单,只要保证buf里有终止符就行:
- 把
buf的大小改成7,读完后手动添加终止符:
char buf[7]; // 多留一个字节放终止符 // ... read(file[0], buf, 6); buf[6] = '\0'; printf("\n%s", buf);
内容的提问来源于stack exchange,提问作者jeff rius
相关产品推荐
相关产品推荐

