C 从文件中读取行的未定义行为

C 从文件中读取行的未定义行为,c,C,当我使用这个函数读取一个文件的内容,然后使用双指针将其拆分为单独的行时,我会有一些奇怪的行为。大约有1/3次,它会扰乱程序中的其他一些内存,导致另一个字符串打印不正确,并且很少会出现malloc“object的校验和不正确”错误。我把它缩小到这个函数,因为我只在调用它时才得到这个行为 File* openFile(char* fn) { FILE* fp = fopen(fn, "rb"); fseek(fp, 0, SEEK_END); long f

当我使用这个函数读取一个文件的内容,然后使用双指针将其拆分为单独的行时,我会有一些奇怪的行为。大约有1/3次,它会扰乱程序中的其他一些内存,导致另一个字符串打印不正确,并且很少会出现malloc“object的校验和不正确”错误。我把它缩小到这个函数,因为我只在调用它时才得到这个行为

File* openFile(char* fn)
{
    FILE* fp = fopen(fn, "rb");
    fseek(fp, 0, SEEK_END);
    long fsize = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    char* contents = malloc(fsize + 1);
    fread(contents, 1, fsize, fp);
    fclose(fp);

    contents[fsize] = 0;

    File* f = malloc(sizeof(File));
    f->len = 0;
    f->rows = NULL;

    int lastNull = 0;
    for(int i = 0; i < fsize; i++)
    {
        if(contents[i] == '\n')
        {
            contents[i] = '\0';
            f->rows = realloc(f->rows, f->len + 1);
            f->rows[f->len++] = &contents[lastNull];
            lastNull = i + 1;
        }
    }

    return f;
}

我不确定该函数是否出错。

realloc(f->rows,f->len+1)中的内存分配不足。

建议修复

// realloc(f->rows, f->len + 1)
f->rows = realloc(f->rows, sizeof *(f->rows) * (f->len + 1));

对于潜在的大文件

typedef struct {
    // int len;
    size_t len;
    char** rows;
} File;

if(contents[i]='\n')
未捕获文件中不以
'\n'
结尾的最后一行

“我不确定函数有什么地方出错。”

for
循环中,行:

f->rows = realloc(f->rows, f->len + 1);  
导致非致命的运行时错误:

非致命运行时错误:“so1.c”,第44行,第23列,线程id 9804:没有足够的空间将表达式强制转换为“指针到指针” 到字符'。”

……对我来说,这最终导致:

致命运行时错误:“so.c”,第44行,第23列,线程id 9804:动态内存已损坏

如果您声明的目的:

“读入文件内容,然后使用双指针将其拆分为单独的行。”

符合您的实际意图,您可以通过一组更简单的步骤来实现这一点。伪代码:

  • fopen
    读取文件以获取行数和最长行数。关闭文件
  • 分配内存,例如:
    char**content=malloc(行*sizeof(*content))(使用前的测试结果。)

  • 为每行分配内存:
    for(i=0;i
    f->rows=realloc(f->rows,f->len+1)
    你知道,指针占用超过1个字节,对吗?另外,检查fopen、malloc和realloc的返回值。所有这些都可能会失败。你为结构选择的typedef名称,
    文件
    虽然合法,但令人困惑。在这种情况下,它太类似于
    文件
    @Gerhardh facepalm,是的,忘记了这一点。
     (f->len+1)*sizeof(File*)
    是正确的吗?它似乎已经解决了这个问题。您可能会考虑将
    len
    重命名为
    rowcount
    或类似名称。另外
    lastNull
    是一个奇怪的名称,因为不涉及
    NULL
    ,但它是当前行开始的索引。是的,我在最后一行有这个问题
    f->rows = realloc(f->rows, f->len + 1);