释放动态分配的 2D 结构

发布于 2024-11-25 06:50:30 字数 2120 浏览 1 评论 0原文

我动态分配了一个结构(概念上与矩阵非常相似)来保存一组字符串。我在尝试释放内存时遇到问题。我的代码如下所示:

# include <stdio.h> 
# include <string.h>
# include <malloc.h>
# define SIZE 2

typedef struct fork{
char** dataPointersArray;
char*  dataArray;
}fork;

int main(int argc, char* argv[]){

fork forkDS;
int i;
char* dataArrayPtr;
unsigned char data[255] = "some data"; /* this is actually a function's output */
int PtrIndex;

/* allocate memory for the arrays */
    forkDS.dataPointersArray = (char**) calloc(SIZE ,sizeof(char*));

    if(forkDS.dataPointersArray == NULL){
        printf("couldn't allocate memory \n");

    }

    forkDS.dataArray = (char*) calloc(SIZE, 255);

    if( forkDS.dataArray == NULL){
        free(forkDS.dataPointersArray);
        printf("couldn't allocate memory \n");

    }
    dataArrayPtr = forkDS.dataArray;
    for(i = 0; i < SIZE; i++){
    /* update the dataPointers Array */
        forkDS.dataPointersArray[i] = dataArrayPtr;


        /* copy data into data array */
        memcpy(dataArrayPtr,data,20);

        dataArrayPtr[255] = '\0';

        /* update the pointer of the data array */
        dataArrayPtr = dataArrayPtr + 256;
    }


    for (PtrIndex = 0; PtrIndex < 2; PtrIndex++) {
        if (*(forkDS.dataPointersArray + PtrIndex) != NULL) {
            *(forkDS.dataPointersArray + PtrIndex) = NULL;
        }
    }

    /* DEBUG comment -  this 2 lines works */
    free(forkDS.dataArray); 
    forkDS.dataArray = NULL;

    /* DEBUG comment - the next line fails */
    free(forkDS.dataPointersArray);
    forkDS.dataPointersArray = NULL;


return 0;
}

所以该结构实际​​上包含 2 个数组,一个指向字符串的指针,另一个包含一个接一个对齐的字符串,并以终止 \0 分隔。

代码运行良好,最后的 for 循环也运行良好。第一次调用 free 也有效。问题是最后一次调用 free 失败。 尽管尝试搜索有关该问题的所有可能数据,但我找到的所有示例都考虑了这样的情况:保存字符串的第二个数组在 for 循环中逐步分配,然后也在 for 循环中释放。

我想避免在循环中使用动态分配,因此我的代码看起来不同。

有谁知道问题是什么?

=================================================== ======================================

非常感谢所有回答我的人。最终,这个bug被解决了。问题在于 dataPointersArray 在其他代码段中填充了超过 SIZE 的元素,乍一看似乎是无辜的,但实际上导致了 free 调用失败。

再次感谢您的评论! 沙查尔

I've dynamically allocated a structure, conceptually very similar to a matrix, to hold a set of strings. I've encountered a problem while trying to free the memory. My code looks like this:

# include <stdio.h> 
# include <string.h>
# include <malloc.h>
# define SIZE 2

typedef struct fork{
char** dataPointersArray;
char*  dataArray;
}fork;

int main(int argc, char* argv[]){

fork forkDS;
int i;
char* dataArrayPtr;
unsigned char data[255] = "some data"; /* this is actually a function's output */
int PtrIndex;

/* allocate memory for the arrays */
    forkDS.dataPointersArray = (char**) calloc(SIZE ,sizeof(char*));

    if(forkDS.dataPointersArray == NULL){
        printf("couldn't allocate memory \n");

    }

    forkDS.dataArray = (char*) calloc(SIZE, 255);

    if( forkDS.dataArray == NULL){
        free(forkDS.dataPointersArray);
        printf("couldn't allocate memory \n");

    }
    dataArrayPtr = forkDS.dataArray;
    for(i = 0; i < SIZE; i++){
    /* update the dataPointers Array */
        forkDS.dataPointersArray[i] = dataArrayPtr;


        /* copy data into data array */
        memcpy(dataArrayPtr,data,20);

        dataArrayPtr[255] = '\0';

        /* update the pointer of the data array */
        dataArrayPtr = dataArrayPtr + 256;
    }


    for (PtrIndex = 0; PtrIndex < 2; PtrIndex++) {
        if (*(forkDS.dataPointersArray + PtrIndex) != NULL) {
            *(forkDS.dataPointersArray + PtrIndex) = NULL;
        }
    }

    /* DEBUG comment -  this 2 lines works */
    free(forkDS.dataArray); 
    forkDS.dataArray = NULL;

    /* DEBUG comment - the next line fails */
    free(forkDS.dataPointersArray);
    forkDS.dataPointersArray = NULL;


return 0;
}

So the structure actually contains 2 arrays, one of pointers to strings, and the other one contains the strings aligned one after the other, separated by a terminating \0.

The code works fine, and the for loop in the end works as well. The first call to free also works. The problem is that the last call to free fails.
Although trying to search all possible data on the issue, all the examples I've found regarded the case where the second array, which holds the strings, is allocated step by step in a for loop, and freed afterwards in a for loop as well.

I wanted to avoid using dynamic allocation in a loop, and therefore my code looks different.

Does anyone know what the problem is?

======================================================================================

Thanks a lot to all of you who answered me. Eventually, the bug was solved. The problem was that the dataPointersArray was filled with more than SIZE elements in some other piece of code, which seemed innocent at first, and actually caused the free call to fail.

Thanks again for the comments!
Shachar

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

﹎☆浅夏丿初晴 2024-12-02 06:50:30

您正在分配 SIZE*255 字节,但使用 SIZE * 256 字节:

forkDS.dataArray = (char*) calloc(SIZE, 255); 
dataArrayPtr = forkDS.dataArray;   

//SIZE TIMES loop:
    dataArrayPtr = dataArrayPtr + 256; 

因此,当您对指针进行 NULL 处理时,您可能会覆盖 free 正在查找的 malloc 放置在数组末尾之后的控制数据。

You are allocating SIZE*255 bytes, but using SIZE * 256 bytes:

forkDS.dataArray = (char*) calloc(SIZE, 255); 
dataArrayPtr = forkDS.dataArray;   

//SIZE TIMES loop:
    dataArrayPtr = dataArrayPtr + 256; 

So when you are NULLing the pointers, you probably overwrite control data placed past the end of the array by malloc that free is looking for.

物价感观 2024-12-02 06:50:30

您为包含 SIZE 行(每行 255 个字符)的数组分配了空间。因此,每行的最高索引为 254 = 255 - 1。当您写入 \0 字符时,您将其写入下一行的开头。最后一次迭代之后,您将偏离 SIZE 字节。

另一个细节是:如果任何内存分配失败,程序只会打印其错误消息,但稍后不会停止导致 SEGFAULT。

You allocated the space for an array consisting of SIZE lines with 255 characters each. The highest index on each line therefore is 254 = 255 - 1. As you write the \0 character, you write it at the beginning of the next line. After the last iteration, you would be off by SIZE bytes.

Just another detail: If any of the memory allocations failed, the program would only print its error messages, but it won't stop causing a SEGFAULT later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文