You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:10:57