【问题标题】:Malloc crashes in recursive functionMalloc 在递归函数中崩溃
【发布时间】:2011-11-24 06:37:39
【问题描述】:

我目前正在编写 Burrows-Wheeler 变换的实现,它需要对(大)数组进行排序。由于我想并行化递归排序函数的部分代码,我决定在堆中分配一些局部变量(使用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() 时在 radixsort 的第二次或第三次迭代中崩溃。当输入文件较大(大约 1 MiB)时,它总是崩溃。同样在第 2 或第 3 次迭代中...

手动增加堆没有任何好处。无论哪种方式,都不应该。如果malloc() 无法分配内存,它应该返回一个NULL 指针(而不是崩溃)。

从堆切换回堆栈使程序可以使用任一编译器(只要输入文件足够小)。

那么,我错过了什么/做错了什么?

【问题讨论】:

    标签: c crash malloc


    【解决方案1】:
    if((occurrences = malloc(1024)) == 0)
    
    make that:
    
    if((occurrences = malloc(1024 * sizeof *occurences)) == 0)
    

    但是还有更多的问题……

    更新(1024 = 4 * 256 似乎只是风格......)

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

    [i+1] 索引将寻址超出其大小的数组;

    【讨论】:

    • 另外请检查 NULL 指针,绝对 not 0,在 malloc 之后( ) 调用。
    • @wildplasser:我怎么错过了?使用for(i = 0; i &lt; 255; i++),一切正常。
    • 不,它们不一样。另外:请调整您的尺寸和偏移量。像这样的程序不应该包含除 0 和 1 之外的任何魔术常量(sizeof 是你的朋友)。 for 循环也可以重写为:“for(i = 1; i
    • @PeteWilson:比较 0 和比较 NULL 是完全等价的。 0 是一个空指针常量NULL 扩展到的任何内容也是如此。
    • @wildplasser:是的,它们是一样的。空指针的表示不一定是所有位为零,但常量0 是一个*空指针conatant*`,并且在此上下文中将转换为空指针。 (如果malloc 的声明没有#include &lt;stdlib.h&gt;,您可能会遇到问题,但无论如何都需要#include。)
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 2019-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 2011-08-13
    相关资源
    最近更新 更多