malloc覆盖按值传递的参数

时间:2019-07-08 13:17:23

标签: c arrays malloc undefined-behavior

我想为2D数组分配内存,以使数组的增量内存增加。这意味着array[0]可以容纳1个uint32_t,array [1]可以容纳2个uint32_t,依此类推。将其视为三角形。

我有一个函数,它将最终数组可以容纳的最大变量数作为参数rows。因此,我们有rows个数组(array[0]array[rows-1]),并拥有1到rows的多个变量。

为主数组初始化并分配内存后,我们可以使用for循环进行初始化,然后为每个子数组递增分配。我们必须在两个单独的表达式中执行此操作,因为增量器i是继承变量。

我们应该有这样的东西(我知道我没有free记忆,但这不是问题所在)

#define ROWS 15

int main()
{
    uint32_t** array = triangle2array(FILEPATH, ROWS, DIGITS);
    ...
}

uint32_t** triangle2array(const char* filepath, uint8_t rows, uint8_t digits)
{
    uint32_t** row = (uint32_t**) malloc(rows*sizeof(uint32_t*));
    if (row == NULL) {
        fprintf(stderr, "row memory is not allocated\n");
        exit(EXIT_FAILURE);
    }
    for (size_t i = 0; i < rows; i++) {
        // Initialise memory for sub-array, i.e. arrays that hold the numbers on a specific row
        uint32_t* row[i];
        row[i] = (uint32_t*) malloc((i+1)*sizeof(uint32_t));
        if (row[i] == NULL) {
            fprintf(stderr, "row[%zi] memory is not allocated\n", i);
            exit(EXIT_FAILURE);
        }
        assert(rows == ROWS);
    }
    return row;
}

它不起作用。根据调试器,自变量rows寻址到0x00007FFFFFFFDFA4,而row[0]寻址到0x00007FFFFFFFDFA0。本质上,row[0]rows之前的4个字节被寻址,并且当分配malloc时,内存被铺在rows上,从而给rows一个随机值。

奇怪的是,如果我做一个镜像函数并做基本上相同的事情,它就可以很好地工作:

#define MACRO 15

void example(uint8_t);

int main(void)
{
    example(MACRO);
    return 0;    
}

void example(uint8_t macro)
{
    uint32_t** row = malloc(macro*sizeof(uint32_t*));
    for (size_t i = 0; i < macro; i++) {
        uint32_t* row[i];
        row[i] = malloc((i+1)*sizeof(uint32_t));
    }
    assert(macro == MACRO);
    free(row);
}

老实说,我不知道如何解决这个问题。

1 个答案:

答案 0 :(得分:4)

    for (size_t i = 0; i < rows; i++) {
        // Initialise memory for sub-array, i.e. arrays that hold the numbers on a specific row
        uint32_t* row[i];
        row[i] = (uint32_t*) malloc((i+1)*sizeof(uint32_t));
        if (row[i] == NULL) {
            fprintf(stderr, "row[%zi] memory is not allocated\n", i);
            exit(EXIT_FAILURE);
        }
        assert(rows == ROWS);
    }

您的问题是第uint32_t* row[i];行。我不知道您打算做什么,但是实际上是在row循环的局部声明一个名为i的新数组,大小为for。换句话说,以下作业

row[i] = (uint32_t*) malloc((i+1)*sizeof(uint32_t));

不会分配给您row之前创建的动态数组malloc,而是超出此嵌套数组row的范围。删除虚假声明uint32_t* row[i];,您的代码应该可以正常工作。