在C中,如何在堆中存储和释放一个多维Map,行和列?

slsn1g29  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(75)

我试图使用C语言构建一个数据结构,它允许我记录字符串(表示海拔值),这些字符串的数据描述了Map中点的一些特征。除了对应字符串描述的特征外,每个点还应该有一个对应于经度的坐标(列)和一个对应于纬度的坐标(行)。
我想通过在堆中为行和列分配内存来将此Map输出为空结构。这个想法是,你有一个指针,指向一个指向char的指针,为此你为一个指向char的指针的指针数组分配内存,每个指针指向一行的开头。第一个数组中包含的每个指向char的指针都必须为一个指向char的指针数组分配内存。
这将是一个基本结构。在这个阶段不需要为每个指向char的指针分配字符串,因为字符串将通过阅读一个文本文件来构造,然后通过分配与其开头对应的地址来“指向”。我已经尝试过以这样一种方式分配内存,即指针数组被视为NULL终止的指针数组,即。使用空指针而不是空字节来定义行数组的结束和列上每个点序列的结束。根据测试,这一策略运作良好:使用指针算术(即不索引的数组与计数器)和两个整数计数器,它导致了一个确切的行数,并为每一行,列的确切数目。
然而,当我不得不释放内存时,Valgrind警告我,我的代码正在产生一些内存块的无效释放。

valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s -v ./the_program

我用的是瓦尔格林的咒语。
下面是代码:有人能看出我的错误吗?我错过了什么?

int allocate_memory_for_map_structure(void) // The real function (but what is
                                            // reality?) takes a pointer to some
                                            // data stored in the data segment,
                                            // e.g. values for "width" and
                                            // "height".
{
    char    ***map;
    char    ***swap;
    char    ***swap2;
    char    ***start;
    int     count;
    int     width;
    int     height;

    width = 100; // could be any integer value passed to the function
    height = 75; // same as above
    map = malloc((height + 1) * sizeof(*map));
    if (map == NULL)
        return (-1);
    count = 0;
    swap = map;
    while (count < height){
        *swap = malloc((width + 1) * sizeof(**swap));
        if (*swap == NULL)
            return (clean_lines_in_map_structure(map));
        swap++;
        count++;
    }
    *swap = NULL;
    /*
    test_outcome_of_allocation(map); // I will not add this function's code to the
                                     // question. However, it was a simple test
                                     // that correctly counted the number of rows and
                                     // columns stoppin iterations when NULL
                                     // was reached by dereferencing incremented pointers.
    */
    start = map;
    swap2 = map;
    while (*swap != NULL){
        map = swap;
        swap++;
        free(*map);
    }
    free(start);
    return (0);
}

我很想知道怎么做,但更想知道我犯了什么错误:为什么我写的东西会导致无效的内存释放?

xzv2uavs

xzv2uavs1#

使用双指针初始化和释放数组项是麻烦的,而且容易出错。你应该改用数组语法。
你似乎依赖于空指针哨兵矩阵边界。这可以工作,但传递矩阵维度似乎更可靠。
请注意,if (*map == NULL)中有一个错字:应该是if (*swap == NULL)
以下是修改后的版本:

int clean_lines_in_map_structure(char ***map) {
    for (int i = 0; map[i]; i++) {
        free(map[i]);
    }
    free(map);
    return -1;
}

int allocate_memory_for_map_structure(void) // The real function (but what is
                                            // reality?) takes a pointer to some
                                            // data stored in the data segment,
                                            // e.g. values for "width" and
                                            // "height".
{
    int width = 100; // could be any integer value passed to the function
    int height = 75; // same as above
    char ***map = malloc(sizeof(*map) * (height + 1));
    if (map == NULL)
        return -1;
    for (int i = 0; i < height; i++) {
        map[i] = malloc(sizeof(*map[i]) * (width + 1));
        if (map[i] == NULL)
            return clean_lines_in_map_structure(map);
        // intialize the matrix entries
        for (int j = 0; j < width + 1; j++)
            map[i][j] = NULL;
    }
    map[height] = NULL;
    /* The following two instructions are here only for test. */
    test_outcome_of_allocation(map); // I will not add this function's code to the
                                     // question. However, it was a simple test
                                     // that correctly counted the number of rows and
                                     // columns stoppin iterations when NULL
                                     // was reached by incrementing pointers.
    clean_lines_in_map_structure(map);
    return 0;
}

相关问题