2011-09-24 96 views
0

我目前正在編寫一個Burrows-Wheeler變換的實現,它需要對一個(大)數組進行排序。由於我想對遞歸排序函數的部分代碼進行並行化處理,因此我決定在堆中分配一些局部變量(使用malloc())以防止堆棧溢出或 - 至少使程序正常死亡。這引發了一大堆問題。我將代碼分解爲基本部分(即導致問題的原因)。Malloc在遞歸函數中崩潰

以下代碼無錯地編譯。使用icc編譯時,生成的程序工作正常,但在使用gcc或tcc編譯時會崩潰(隨機)。

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

unsigned char *block; 
int *indexes, *indexes_copy; 

void radixsort(int from, int to, int step) 
{ 
    int *occurrences, *first_index_of, i; 
    if((occurrences = malloc(1024)) == 0) 
     exit(1); 
    if((first_index_of = malloc(1024)) == 0) 
     exit(1); 
    memset(occurrences, 0, 1024); 
    for(i = from; i < to; i++) 
     occurrences[block[indexes[i] + step]]++; 
    first_index_of[0] = from; 
    for(i = 0; i < 256; i++) 
     first_index_of[i + 1] = first_index_of[i] + occurrences[i]; 
    memset(occurrences, 0, 1024); 
    memcpy(&indexes_copy[from], &indexes[from], 4 * (to - from)); 
    for(i = from; i < to; i++) 
     indexes[first_index_of[block[indexes_copy[i] + step]] + occurrences[block[indexes_copy[i] + step]]++] = indexes_copy[i]; 
    for(i = 0; i < 256; i++) 
    if(occurrences[i] > 1) 
     radixsort(first_index_of[i], first_index_of[i] + occurrences[i], step + 1); 
    free(occurrences); 
    free(first_index_of); 
} 

int main(int argument_count, char *arguments[]) 
{ 
    int block_length, i; 
    FILE *input_file = fopen(arguments[1], "rb"); 
    fseek(input_file, 0, SEEK_END); 
    block_length = ftell(input_file); 
    rewind(input_file); 
    block = malloc(block_length); 
    indexes = malloc(4 * block_length); 
    indexes_copy = malloc(4 * block_length); 
    fread(block, 1, block_length, input_file); 
    for(i = 0; i < block_length; i++) 
     indexes[i] = i; 
    radixsort(0, block_length, 0); 
    exit(0); 
} 

即使當輸入是一個非常小的文本文件(大約50個字節),則程序是非常不穩定與後兩者編譯器。它以〜50%的概率工作。在其他情況下,當調用malloc()時,它在基數的第二次或第三次迭代中崩潰。它總是當輸入文件更大時(約1 MiB)崩潰。在第2次或第3次迭代中...

手動增加堆沒有任何好處。無論哪種方式,它不應該。如果malloc()不能分配內存,它應該返回一個NULL指針(而不是崩潰)。

從堆切換回堆棧使得程序可以與任一編譯器一起工作(只要輸入文件足夠小)。

那麼,我錯過了什麼/做錯了什麼?

回答

1
if((occurrences = malloc(1024)) == 0) 

make that: 

if((occurrences = malloc(1024 * sizeof *occurences)) == 0) 

但也有更多的問題...

UPDATE(1024 = 4 * 256似乎僅僅文體...)

for(i = 0; i < 256; i++) 
    first_index_of[i + 1] = first_index_of[i] + occurrences[i]; 

的第[i + 1]指數將解決超出其大小的陣列;

+0

也請在malloc()調用之後檢查*** NULL指針***,絕對***不是0 ***。 –

+0

@wildplasser:我怎麼錯過了?用'for(i = 0; i <255; i ++)',一切都按原樣運行。 – Dennis

+0

@Pete Wilson:我很困惑。他們不一樣嗎? – Dennis