从文件读取时出现分段错误

时间:2011-10-05 17:19:40

标签: c

我有以下功能:

void read_file(char* path, char** data)
{
    FILE*   file = NULL;
    size_t  size, result = 0;

    *data = NULL;
    file = fopen(path, "rb");

    if (file == NULL)// error opening file
    {
        return;
    }

    fseek(file, 0, SEEK_END);
    size = ftell(file) + 1;
    rewind(file);

    *data = (char*)malloc(size);
    if(*data == NULL)
        return;

    result = fread(*data, 1, size, file);
    if (result != size - 1)// error reding file
    {
        *data = NULL;
    }
    printf("LINE=%u\n", __LINE__);
    (*data)[size-1] = '\0';

    printf("LINE=%u\n", __LINE__);
    fclose(file);
    return;
}

我在两个printf("LINE=%u\n", __LINE__);语句之间的行上遇到了分段错误。我不明白为什么会这样。当我查看此行时,似乎(*data)将具有(char *)类型,它当然可以与索引运算符[]一起使用。

我错过了什么?

4 个答案:

答案 0 :(得分:5)

可能if (result != size - 1)测试失败,然后您将*data重置为NULL(这是内存泄漏,BTW),然后您尝试写入(*data)[size-1] - 哎呀!

答案 1 :(得分:1)

一些指示:

ftell在失败时返回-1,所以如果是这种情况则为0 size = ftell(file) + 1;

某些平台上的

size_t是unsigned int,考虑到这一点可能会很好。

执行*data = NULL;并不是一个好主意,首先将其释放free( *data );

在代码中添加一些if语句来捕获错误,不要认为一切都会正常工作 例如assert( size>0 );

答案 2 :(得分:0)

我已经测试了你的代码并且它适用于我 - 我已经添加了文件大小的返回以正确地将数据传递给fwrite。

> ./a.out arm-2010.09-good.tar.bz2 | sha1sum && sha1sum arm-2010.09-good.tar.bz2 
alloc size of 37265592
6bdff517bcdd1d279fc84ab3a5fbbca34211a87c  -
6bdff517bcdd1d279fc84ab3a5fbbca34211a87c  arm-2010.09-good.tar.bz2

此外,Valgrind报告没有任何警告和错误,所以......好吧!

#include <stdio.h>
#include <stdlib.h>

size_t read_file(char* path, char** data)
{
    FILE*   file = NULL;
    size_t  size, result = 0;

    *data = NULL;
    file = fopen(path, "rb");

    if (file == NULL)// error opening file
    {
        return 0;
    }

    fseek(file, 0, SEEK_END);
    size = ftell(file) + 1;
    rewind(file);

    fprintf(stderr, "alloc size of %i\n", size);
    *data = (char*)malloc(size);
    if(*data == NULL)
        return 0;

    result = fread(*data, 1, size, file);
    if (result != size - 1)// error reding file
        *data = NULL;
    (*data)[size-1] = '\0';
    size--; // report file size

    fclose(file);
    return size;
}

int main(int argc, char** argv)
{
    char* data;
    if(argc<2)
        return 0;
    size_t siz = read_file(argv[1], &data);
    if(data) {
        fwrite(data, 1, siz, stdout);
        free(data);
    }
    else {
        fprintf(stderr, "No data returned\n");
    }
    return 0;
}

答案 3 :(得分:0)

以下是问题的可能来源:

if (result != size - 1)// error reding file
{
    *data = NULL;
}
printf("LINE=%u\n", __LINE__);
(*data)[size-1] = '\0';

如果 读取文件时出错,会发生什么?您将*data设置为NULL,然后立即尝试取消引用它 - 坏juju。

请注意,这也会导致内存泄漏;你没有释放*data所指向的记忆。

重新构建代码,以便在读取操作成功时仅执行(*data)[size-1] = '\0'

if (result != size - 1)
{
  free(*data);
  *data = NULL;
}
else                    
{                       
  (*data)[size-1] = 0;  
}