调用strcpy触发SIGSEGV崩溃的原因:无需malloc可行吗?
问题根源与解决方案分析
咱们直接说核心问题:你的崩溃完全是野指针导致的,和你尝试追加\0的操作没有任何关系。
为什么会崩溃?
看你定义的数组:
char* str[100];
这是一个指针数组,里面的100个元素都是char*类型的指针,但这些指针完全没有初始化——它们指向的是内存里的随机地址(也就是所谓的“野指针”)。当你调用strcpy(str[strCount], line)时,你是在把line里的内容往一块不属于你的、未知的内存区域拷贝,这种操作属于未定义行为,崩溃是必然的结果。
你尝试用sprintf追加\0完全是无用功:fgets函数本身就会自动在读取到的字符串末尾添加终止符\0,所以line本身已经是合法的C字符串了,不需要额外手动追加。而且你的sprintf写法还有问题——在同一个缓冲区line里同时读写,这本身也是未定义行为,虽然这里没引发新问题,但绝对是错误的用法。
为什么malloc之后崩溃消失了?
当你打开注释里的str[strCount]=malloc(MAX_LINE_SIZE);时,你给每个指针str[strCount]分配了一块合法的、属于你的内存空间。这时候strcpy有了合法的目标地址,自然就能正常工作,不会再触发崩溃。
关于“该场景无需malloc”的说法
说这句话的人大概率是混淆了指针数组和二维字符数组的区别:
- 如果你把
char* str[100];改成char str[100][MAX_LINE_SIZE];,这是一个二维字符数组,每个元素都是一个长度为MAX_LINE_SIZE的字符数组,本身已经在栈上分配了内存空间,这时候确实不需要malloc,直接用strcpy就行。 - 但你的代码用的是指针数组,每个指针都需要手动分配内存才能使用,否则就是野指针。
修正后的代码示例
方式一:使用malloc分配内存(灵活,适合需要动态调整内存大小的场景)
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX_LINE_SIZE 10 int main() { char* str[100]; int strCount = 0; char cCmd[] = "<some command>|awk '{print $1}'"; FILE *fp = popen(cCmd, "r"); // 注意:这里应该判断fp是否为NULL,而不是cCmd(cCmd是栈数组永远不会为NULL) if (fp != NULL) { char line[MAX_LINE_SIZE]; // 加上数组边界检查,防止strCount超过100导致越界 while (fgets(line, sizeof(line), fp) != NULL && strCount < 100) { str[strCount] = malloc(MAX_LINE_SIZE); // 一定要检查malloc是否成功 if (str[strCount] == NULL) { perror("malloc failed"); break; } strcpy(str[strCount], line); // strip(str[strCount]); strCount++; } // 别忘了释放分配的内存,避免内存泄漏 for (int i = 0; i < strCount; i++) { free(str[i]); } // 关闭popen打开的文件指针 pclose(fp); } return 0; }
方式二:使用二维字符数组(无需malloc,适合固定大小的场景)
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX_LINE_SIZE 10 #define MAX_STR_COUNT 100 int main() { // 二维字符数组,每个元素自带栈内存 char str[MAX_STR_COUNT][MAX_LINE_SIZE]; int strCount = 0; char cCmd[] = "<some command>|awk '{print $1}'"; FILE *fp = popen(cCmd, "r"); if (fp != NULL) { char line[MAX_LINE_SIZE]; while (fgets(line, sizeof(line), fp) != NULL && strCount < MAX_STR_COUNT) { strcpy(str[strCount], line); // strip(str[strCount]); strCount++; } pclose(fp); } return 0; }
额外注意点
你代码里还有一个小错误:if(cCmd != NULL)这个判断完全没有意义,cCmd是栈上的数组变量,永远不可能为NULL。你应该判断的是fp != NULL,因为popen可能会因为命令执行失败等原因返回NULL。
内容的提问来源于stack exchange,提问作者anurag86
相关产品推荐
相关产品推荐

