簡體   English   中英

我在分配內存時遇到問題。(也許)

[英]I have a problem to allocate memory.(maybe)

有輸入文件; 未排序的長類型數字。(大約 100 萬個)我想對輸入文件中的數字進行排序。 為了分配數組的內存,我使用了 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;
}

問題在於代碼使用ftell()查找文件中的字節數,然后分配該數據的size

然而,當從文件中讀取時,它試圖讀取四倍的數據,因為元素計數和元素大小傳遞給fread()

如果輸入文件是一大塊二進制 long(與本地硬件格式相同),則可以一次性完成fread()處理。 這意味着您的大小是ftell()結果,但元素計數是one

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

這里有很多問題,我認為這甚至不是實際的代碼。 那些立即引人注目的:

  • 您正在嘗試打開一個名為argv[1]的文件,而不是命令行中給出的文件名。 去掉引號。

  • 您為size個字節分配內存,然后嘗試讀取size * 4個字節,並且不檢查讀取了多少個字節

  • 不要malloc的返回值

  • sizeof arr只給你一個指針的大小,而不是你擁有的數據。 你有size ,使用它。

  • 你的 while 循環有一個與外部同名的新變量,兩者都沒有改變,所以循環是永恆的

  • 如果你不能打開一個文件,你釋放一個未分配的指針

所以檢查你的編譯器的警告。 想想你在做什么,你給函數的參數是什么意思。 檢查返回值。 使用調試器逐行執行代碼。

確切的原因只能在您解決其他問題后才能確定,甚至可能因此而得到解決。 如果這是確切的代碼,那么最后一個可能就是原因。 調試器會告訴你。

有很多事情需要注意,沒有特別的嚴重程度

  • 始終驗證參數

你的程序似乎沒有驗證有點糟糕的參數,開始時的快速聲明就可以完成這項工作

 /* 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 結果

這是一個流行的我是否投了 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作用域

    在本地(在for loop內部)中有多個變量i聲明,而全局范圍則不會這樣做。

  • sizeof()用於 poniters 時要小心

這個語句sizeof( arr )總是給出指針的大小而不是指針指向的數據的大小,下面的語句

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

對我來說沒有多大意義,我無法評估這在您的程序上下文中是否真的有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM