无法使用write()向标准输出写入内容的技术问题排查
问题分析与修复方案
让咱们一步步拆解你遇到的几个问题,逐个解决:
1. write() 无法输出到控制台的核心原因
看你代码里的write调用:
write(fd, &s, 1)
这里犯了两个关键错误:
- 第一个错误:
&s是取指针变量本身的地址,不是当前要输出的字符s[i]的地址!应该写成&s[i]或者s+i,这样才是指向第i个字符的指针。 - 第二个错误:循环条件
i != sizeof(s) - 1完全不对!s是char*类型,sizeof(s)得到的是指针的大小(32位系统是4字节,64位是8字节),不是你用sprintf生成的字符串长度。你已经通过sizeN拿到了字符串的实际长度,应该把这个值传给myfunction,用它来控制循环次数。
2. fprintf(stderr) 输出格式异常的原因
你用了:
fprintf(stderr, "%s\n", &s[i]);
%s格式符会从传入的地址开始,一直输出到遇到\0结束符为止。所以每次循环,你都是输出从s[i]到字符串末尾的子串,自然会出现那种越来越短的重复输出。
如果想每次输出单个字符,应该用%c格式符:
fprintf(stderr, "%c\n", s[i]);
如果只是想验证字符串内容,完全没必要在循环里做,直接在调用myfunction之前用fprintf(stderr, "%s", buffer)输出一次就够了。
3. stdout 无输出、stderr 正常输出的原因
这是标准IO的缓冲机制导致的:
stderr是无缓冲的,所有写入的数据会立即输出到控制台。stdout是行缓冲的,只有当输出包含换行符\n,或者缓冲区被填满,或者手动调用fflush(stdout)时,数据才会被刷新到控制台。
你之前用fprintf(stdout, "%d\n", &s[i])时,如果没有正确输出换行(或者参数写错成了指针地址而非字符本身),数据会留在缓冲区里,直到程序结束才会输出;如果程序异常退出,甚至可能完全看不到。
修复后的完整代码示例
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <string.h> // 假设你原有的wastesometime实现 void wastesometime(int n) { for(int j=0; j<n; j++); } // 修改myfunction:接收字符串长度参数,修正write参数与循环条件 void myfunction(char *s, int fd, int str_len, int n){ for(int i = 0; i < str_len; ++i){ // 可选:验证单个字符输出 fprintf(stderr, "%c", s[i]); // 正确写入当前字符到指定文件描述符 if( write(fd, &s[i], 1) < 0){ perror("Error: Write problems."); } wastesometime(n); } // 手动刷新stdout缓冲区,确保内容立即显示(可选但推荐) if(fd == STDOUT_FILENO){ fflush(stdout); } // 给stderr的验证输出加换行,让格式更整洁 fprintf(stderr, "\n"); } int main(){ int i = 2; // 示例进程编号 int n = 1000; char buffer[256]; // 生成目标字符串并获取实际长度 int sizeN = sprintf(buffer, "This is process %d with ID %ld and parent id %ld\n", i, (long)getpid(), (long)getppid()); // 传入字符串实际长度sizeN myfunction(buffer, STDOUT_FILENO, sizeN, n); return 0; }
关键修改点总结
- 给
myfunction添加字符串长度参数,替代错误的sizeof(s)循环判断逻辑。 - 把
write(fd, &s, 1)改成write(fd, &s[i], 1),确保写入的是当前目标字符。 - 修正
fprintf的格式符,避免异常的子串重复输出。 - 可选:手动刷新stdout缓冲区,确保内容立即显示在控制台。
内容的提问来源于stack exchange,提问作者K-Log
相关产品推荐
相关产品推荐

