【问题标题】:Read multiple lines from file using fgets() and store to array of pointers使用 fgets() 从文件中读取多行并存储到指针数组
【发布时间】:2019-01-24 14:33:48
【问题描述】:

我正在尝试在“批处理文件模式”下实现自定义外壳。假设我有一个名为“batchfile”的文件,其中包含:

ls –l
pwd
ps
touch hello
ls -l ; cat file ; grep foo file2
ls -l && cat file
quit

调用./myShell batchfile,我想分别执行命令。但是,当我尝试使用 fgets() 从文件中读取行然后将它们存储到数组 (char * batch_cmds[512]) 时,我得到:

分段错误(核心转储)

这是我目前的代码:

int main(int argc, char *argv[]){
    if (argc >=2){
        char str[512];
        char *batch_cmds[512];
        int i=0; 
        FILE *fp;

        fp = fopen(argv[1], "r");

        while(fgets(str,512, fp)!=NULL){
            strcpy(batch_cmds[i], str);
            i++;
        }
    fclose(fp);

我不明白为什么会弹出这个错误。

【问题讨论】:

  • 您没有为batch_cmds 分配任何内存,因此(例如)batch_cmds[0] 没有指向内存中存储字符串的有效位置
  • C 使用旧式堆栈/堆内存管理,因此您需要了解指针和 malloc 的工作原理。
  • @ChrisTurner 是正确的,batch_cmds 是一个空指针,你需要管理内存或静态分配它,我建议使用链表并在成功读取一行时分配每个节点。

标签: c bash shell pointers fgets


【解决方案1】:

您为指针本身保留了空间,但没有为每个此类指针应指向的每个字符串保留空间。每个batch_cmds[i] 指向“某处”,至少不是指向您分配的对象;然后,当您调用strcpy(batch_cmds[i], str); 时,您将str 的内容写入“某处”并产生未定义的行为(例如崩溃;实际上语句batch_cmds[i] 访问了一个未初始化的数组,并且它本身已经是未定义的行为;但仅此一项很少导致崩溃)。

代替

strcpy(batch_cmds[i], str);

batch_cmds[i] = strdup(str);

命令strdup 执行这两个操作 - (1) 保留足够大的内存以容纳 str 的内容和 (2) 然后复制 str 的内容。这相当于batch_cmds[i] = malloc(strlen(str)+1); strcpy(batch_cmds[i], str));

此外,检查i 是否为<512,这样batch_cmds[i] 不会超出数组边界。

【讨论】:

  • 非常感谢。无法更好地解释它。效果很好。
【解决方案2】:

行:

char *batch_cmds[512];

声明一个由 512 个指向 char 的指针组成的数组,但这些指针是未初始化的(狂野的,悬空的,任你选择)。

您的选择:

  1. 在栈上声明一个二维数组:

    char batch_cmds[512][512];
    
  2. 使用动态内存管理在堆上分配字符串:

    char *batch_cmds[512];
    int i;
    for(i = 0; i < 512; i++)
    {
        batch_cmds[i] = malloc(string_length);
        if(batch_cmds[i] == NULL)
        {
             // handle alloc error
        }
    }
    
    // Code that uses batch_cmds...
    
    for(i = 0; i < 512; i++)
    {
        free(batch_cmds[i]);
        batch_cmds[i] = NULL;
    }
    
  3. 使用strdup 将指针分配给batch_cmds 中的char(在Stephan Lechner 的回答中演示)。请注意,strdup 在后台也使用堆内存,因此当您使用完返回的指针时也必须将它们传递给 free,以避免内存泄漏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多