【问题标题】:Assignment to variable gives segmentation fault in completely unrelated function分配给变量会导致完全不相关的函数出现分段错误
【发布时间】:2012-04-26 05:18:45
【问题描述】:

我复制了一些代码,这些代码只是将文件读取到字符串并从旧程序打印字符串。它工作正常,所以我决定对其进行一些修改。新程序是

#include <stdio.h>
#include <string.h>

int main() {
    FILE *itemlist = fopen("itemlist", "r");
    char *currentstring, charbuffer[2];
    // char itemstart = 0;
    while (fgets(charbuffer, 2, itemlist)) {
        strcat(currentstring, charbuffer);
    }
    printf("%s", currentstring);
    return 0; 
}

它按预期工作。但是当我取消注释 itemstart 行时,它会出现分段错误。我什至没有使用它,就我而言,将 char 初始化为 0 并不违法。我认为这是类型的问题,然后我将其更改为 short ,然后更改为 int ,它仍然给出段错误。

但后来我删除了= 0 部分,它又可以工作了。然后我决定放回去,用gdb调试二进制,segfault在strcat

这怎么可能?

【问题讨论】:

  • currentstring 指向什么?
  • 暂时没有,只是一个空字符串。当我让currentstring 指向 NULL 时,它会出现段错误。
  • 那是修辞。你是对的,它指向nothing。随机记忆。你认为当你修改随机存储器时会发生什么?你认为它会指向哪里,这样你就可以随意写信给它?
  • 哦,对了,我忘了。文本中的每一行都有不同的长度并且没有长度限制,这就是我没有使用malloc的原因。我想我可以阅读该行,获取长度然后分配,但是这个项目列表将读取大约 20000 个项目,所以我不确定这是否是一件好事。

标签: c string segmentation-fault variable-assignment


【解决方案1】:

您必须为currentstring 变量分配空间并控制其大小以避免段错误/堆损坏。

#define MAX_BUFFER_SIZE 32
//...
FILE *itemlist = fopen("itemlist", "r");
char *currentstring = malloc(MAX_BUFFER_SIZE+1);
char *tmpbuf;
char charbuffer[2];
// char itemstart = 0;
int bytesloaded = 0;
while (fgets(charbuffer, 2, itemlist)) {

    if(bytesloaded + 2 > buf_size) {
       /* call realloc() */
        buf_size += MAX_BUFFER_SIZE;
        tmpbuf = realloc(currentstring, buf_size);
        if(tmpbuf == NULL) { /* Get off loop. Using break or return. */
             break; 
        } 
        currentstrig = tmpbuf;
     }
    memcpy(currentstring + bytesloaded, charbuffer, 2);
    bytesloaded += 2;
}
//... 
free(currentstring);

我没有测试过,但我相信它有效。

【讨论】:

    【解决方案2】:

    currentstring 是一个悬空指针,因此strcat(currentstring, charbuffer); 会导致未定义的行为。

    可能取消注释 char itemstart = 0 会将一些内存初始化为 0 并且访问冲突是可见的,但这只是一个猜测。未定义的行为意味着任何事情都可能发生。

    你应该为currentstring分配内存:

    currentstring = malloc(10); //or whatever length you need
    

    【讨论】:

    • 你更正了他的代码,但你没有回答他的问题:)
    • 这将是一个读取格式为id = [name, properties, ...]的项目列表的程序,因此每行的长度可以是10或150。
    • @EldritchConundrum 我做到了。未定义的行为。再次阅读答案。
    • @user1002327 那么,您要么分配足够大的缓冲区,要么使用不同的方法。
    • itemlist 是我无法删除的,足够大的缓冲区可能会浪费大量内存。我需要读取约 20000 个项目,进行一些处理,并将所有内容写回另一个文件(应该更小,大约 200 个项目左右)。但是感谢您的回答,这似乎是原因。
    【解决方案3】:

    由于 C 语言的不安全性,取消注释无关行时可能会出现段错误。错误程序的最终行为是由编译器做出的细微选择决定的。

    当遇到这种疯狂时,您应该首先尝试更正您的代码。当然,这并不总是那么容易。在一个 8 行的程序上,你应该没问题。

    【讨论】:

      【解决方案4】:

      你需要为当前字符串分配一些空间。

      【讨论】:

        猜你喜欢
        • 2010-10-25
        • 1970-01-01
        • 2021-10-30
        • 2015-08-06
        • 1970-01-01
        • 1970-01-01
        • 2012-07-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多