我在分配内存时遇到问题。(也许)

时间:2019-04-08 04:57:18

标签: c

有输入文件;未排序的长型数字。(大约一百万) 我想对输入文件中的数字进行排序。 为了分配数组的内存,我使用了fseek和ftell。 但是发生了分割错误。 我该如何修复代码?

int main( int argc, char *argv[] )
{
    long *arr;
    FILE *fp = NULL;
    FILE *fp2 = NULL;
    int   i = 0;
    long  size, count;

    fp  = fopen( "argv[1]", "r" );
    fp2 = fopen( "sorted",  "w" );
    if ( fp == NULL || fp2 == NULL )
        printf( "error \n" );
    else
    {
        fseek( fp, 0, SEEK_END );
        size = ftell( fp );
        arr = ( long * ) malloc( size );
        count = fread( arr, size, 4, fp );

        Quicksort( arr, 0, sizeof( arr ) / sizeof( int ) - 1 );

        while ( i != ( sizeof( arr ) / sizeof( int ) - 1 ) )
        {
            int i = 0;
            int j;
            for ( j = 0; j < 5; j++ )
                fwrite( arr, size, 1, fp2 );
        }
    }
    fclose( fp );
    free( arr );
    fclose( fp2 );
    return 0;
}

3 个答案:

答案 0 :(得分:4)

问题是代码使用ftell()查找文件中的字节数,然后分配size的数据量。

但是,由于元素数量元素大小,当从文件中读取文件时,它试图读取的数据量是原来的四倍>传递给fread()

如果输入文件是很大的二进制长块(与本地硬件的格式相同),则可以一次完成fread()个批次。这意味着您的大小是ftell()的结果,但元素数是 1

fseek( fp, 0, SEEK_END );
size = ftell( fp );
arr = ( long * ) malloc( size );
count = fread( arr, size, 1, fp );  // read the whole block in a single go

答案 1 :(得分:3)

这里有很多问题,我认为这甚至不是实际的代码。那些立即值得注意的:

  • 您正在尝试打开一个名为argv[1]的文件,而不是命令行中提供的文件名。删除引号。

  • 您为size字节分配内存,然后尝试读取size * 4字节,而不检查已读取的字节数

  • 不要转换malloc

  • 的返回值
  • sizeof arr仅为您提供指针的大小,而不为您提供的数据。您有size,请使用它。

  • 您的while循环具有与外部名称相同的新变量,两个变量均未更改,因此循环是永恒的

  • 如果无法打开文件,则释放未分配的指针

因此,请检查编译器的警告。考虑一下您在做什么,为函数提供的参数意味着什么。检查返回值。使用调试器逐行浏览代码。

确切的原因只能在解决其他问题后才能确定,甚至可能会得到解决。如果这是确切的代码,那么最后一个可能是原因。调试器会告诉您。

答案 2 :(得分:3)

有一堆需要注意的事情,没有特别的严重程度

  • 始终验证参数

您的程序似乎没有验证参数,这很不好,一开始的快速声明即可完成工作

 /* Always do some argument checking, Assuming in your case command line is 2 */
    if ( argc != 2 ) 
    {
        printf("Invalid arguments ");
        printf("Usage %s <filename>\n", argv[0]);
        exit(0);
    }
  • 始终检查返回值

检查返回值并验证返回值始终是一个好主意,例如当然有一些例外printf,但诸如fopenmalloc之类的情况并不构成犯罪。检查返回值

/* Return Type Validations are mandatory */
    fp  = fopen( argv[1], "r" );
    if( fp == NULL )
    {
        printf("Error Opening file %s\n", argv[1]);
        exit(0);
    }
  • 不要转换malloc结果

这是一个受欢迎的Do I cast the result of malloc,答案是否定的

  • fread

man fread

可能是由于误解了函数的行为
The function fread() reads nmemb items of data, each size bytes long,
       from the stream pointed to by stream, storing them at the location
       given by ptr.

通过编写类似的语句,您基本上可以读取所需数据的4倍

count = fread( arr, size, 4, fp );
  • 混合localglobal范围

    在本地(在i内)有多个变量for loop的声明,而全局范围则没有。

  • 在使用sizeof()来做毛衣时要小心

此语句sizeof( arr )始终给出指针的大小,而不是指针所指向的数据的大小,以下语句

Quicksort( arr, 0, sizeof( arr ) / sizeof( int ) - 1 );

对我来说没有多大意义,而且我无法评估在您的程序上下文中这是否真的有效。