如何将/bin/ls -l管道输出保存为字符串?现有代码出现段错误
解决popen读取命令输出时的Segmentation Fault问题
首先看你代码里的核心问题:那行scanf(path, s)完全是错误的,这就是触发段错误的直接原因。
为什么会这样?
s是一个未初始化的指针,它没有指向任何有效的内存空间,scanf尝试往这个空指针指向的地址写数据时,直接访问了非法内存,触发了segmentation fault。- 而且
scanf的作用是从标准输入读取格式化数据,你已经用fgets把命令输出读到path里了,根本不需要用scanf来处理这个内容。
要把ls -l的输出完整保存到字符串里供后续使用,正确的做法是动态分配内存,把每行读取到的内容逐步拼接起来。下面是完整的正确实现:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *fp; int status; char line[256]; // 缓冲区存每行内容,256长度足够应对大部分命令行输出的行 char *output = NULL; // 用来保存最终的完整输出 size_t total_length = 0; // 打开命令的读管道 fp = popen("/bin/ls -l", "r"); if (fp == NULL) { perror("popen failed"); // 用perror输出更详细的错误原因 return EXIT_FAILURE; } // 逐行读取输出 while (fgets(line, sizeof(line), fp) != NULL) { size_t line_len = strlen(line); // 重新分配内存,预留当前行长度+1的空间给字符串结束符 char *temp_buffer = realloc(output, total_length + line_len + 1); if (temp_buffer == NULL) { perror("realloc failed"); free(output); // 出错时要释放已分配的内存,避免内存泄漏 pclose(fp); return EXIT_FAILURE; } output = temp_buffer; // 把当前行复制到output的末尾 strcpy(output + total_length, line); total_length += line_len; } // 关闭管道 status = pclose(fp); if (status == -1) { perror("pclose failed"); free(output); return EXIT_FAILURE; } // 现在output里就是完整的命令输出了,可以在这里做后续处理 if (output != NULL) { printf("保存的命令输出:\n%s", output); free(output); // 记得释放动态分配的内存 } return EXIT_SUCCESS; }
关键细节说明:
- 用
realloc动态调整内存大小:避免固定长度数组不够用的问题,每次读取一行后扩展输出字符串的空间。 - 错误处理更严谨:用
perror替代简单的printf,能直接输出系统调用失败的具体原因;每次出错时都释放已分配的内存,避免内存泄漏。 - 内存管理:动态分配的
output一定要在最后(或出错时)用free释放,否则会造成内存泄漏。
再回头看你原来的代码问题总结:
- 错误使用
scanf:你需要的是字符串拼接,而不是从输入读取数据,scanf完全不适合这个场景。 - 未初始化指针
s:未指向有效内存就尝试写入,直接触发段错误。
内容的提问来源于stack exchange,提问作者AFC
相关产品推荐
相关产品推荐

