C语言 从动态创建的二维字符数组中释放内存

d8tt03nd  于 2023-04-29  发布在  其他
关注(0)|答案(2)|浏览(117)

下面是我如何声明数组

const int SIZE = 128;
char line[SIZE];
char **lineArray = NULL;
char **lineArray = malloc(count * sizeof(char*));
                
for (int i = 0; i < count; ++i) {
    lineArray[i] = (char *)malloc(SIZE* sizeof(char*));
}

下面是我尝试清除它的地方。..

for (int i = 0; i < count; i++ )
{
    free(lineArray[i]); <<- program dies here
}
free(lineArray);

我当然看了其他一些有同样问题的问题,我想我可能在某些情况下没有使用strcopy,但没有。看起来很光明正大
strcpy(*(lineArray+i), line);是我写的唯一时间。
说实话,我这周只学了指针和一堆其他的东西,我看了我的讲座视频,说实话,它没有那么没用。

jpfvwuh4

jpfvwuh41#

1.如果你的代码不能编译,就不要强制转换malloc的结果,这意味着你正在使用C++编译器编译C代码,这是不正确的。

  1. char **lineArray不是一个2D数组的指针。要分配2D数组,您需要使用pointer to array
  2. const int SIZE = 128;不是一个常量表达式,并且您的line将是一个VLA,并非所有编译器都支持它(例如msvc不支持它)。
    1.请使用正确的型号。它是size_t而不是int
#define  SIZE 128

int main(void)
{
    size_t count;

    count = getcount();

    char (*lineArray)[SIZE] = malloc(count * sizeof(*lineArray));

    if(lineArray)
    {
        //do something with the 2D char array
    }

    free(lineArray);
}
vuktfyat

vuktfyat2#

请注意,C在非常低的水平上运行。您实际上并不像其他编程语言那样使用数组。在这里,它们可能更愿意被理解为列表。
在C中,更多地从汇编器的Angular 来看待它。C中的每个数组基本上就是一个指针。如果使用方括号,则指定相对于此指针的偏移量。你要做的就是计算新的内存地址:

char myArray[12];
    
    /*
     * Points to the start of the Array.
     */
    
    char *arrayStart = myArray;
    
    /*
     * Points to the 10th element in the array, which is the
     * same as myArray[10].
     */
     
    char *elem10 = arrayStart + 10 * sizeof(char);

因此,这里要实现的并不是一个二维数组,而是一个充满指向其他内存位置的指针的数组。这些存储器位置中的每一个可以是任何大小,如果它们存在的话。
我给予两个例子:

动态方式(无2D-Array)

如果我想和你做同样的事,我会这么做。这不是2D数组!它是一个指向指针数组的指针。因此,您保留了可以包含这些指针的内存,但它们可能根本不存在。

const int lineCount = 20;
    const int lineSize = 128;
    
    /*
     * Instead of malloc, which only allocates a block of memory,
     * I use calloc, since it also initializes this memory space.
     * 
     * The following code creates an array of pointers to char
     * arrays. Every item is automatically set to 0.
     *
     * Since all *alloc functions return 0 when the allocation fails,
     * which is conveniently also the value for 'false', you can do
     * a simple if check.
     */
    
    char **lines = (char**)calloc(lineCount, sizeof(char*));
    
    if (!lines)
        perror("Unable to allocate space for the line array.");
    
    /*
     * The next step would be to initialize the actual line buffers.
     * Notice that the pointers to the line buffers will automatically
     * be set to 0, if the allocation fails.
     */
     
    for (int lineIndex = 0; lineIndex < lineCount; lineIndex++)
        lines[lineIndex] = (char*)calloc(lineSize, sizeof(char));
      
    /*
     * Now we free everything: First we free eacht line, then the
     * lineBuffer itself.
     */
     
    for (int lineIndex = 0; lineIndex < lineCount; lineIndex++)
        free(lines[lineIndex]);
        
    free(lines);

静态方式(2D-Array)

2D数组可以被认为是一个表。有固定数量的行和列。这也是您的实现的不同之处。当你处理指向指针的指针时,行的数量是固定的,但是每行的列数是任意的。实现“真实的”2D阵列可以如下完成:

const int lineCount = 20;
    const int lineSize = 128;
    
    /*
     * Allocate the total space for the array.
     * Its size will never change. Every line will have 128 chars.
     */
     
    char *array = (char*)calloc(lineCount * lineSize, sizeof(char));
    
    if (!array)
        perror("Unable to allocate space for the array.");
    
    /*
     * Let's say we want to select the 12th element in the 3rd line.
     * We have to calculate the offset relativ to the start of the
     * array (since it is also just a pointer). 
     *
     * This is actually the same thing the compiler does, when 
     * dealing with double indices as in array[row][col].
     */
    
    int line = 3;
    int element = 12;
    
    array[(line * lineSize) + element] = 'a';
    
    /*
     * Since the array is one solid block, we can free everything
     * at once.
     */
    
    free(array);

哪种方式更好?

这完全取决于你所做的工作的复杂性。在某些情况下,你必须依赖可变长度。但是,每个 *alloc调用都会产生一定的开销。大型环境中的内存管理绝不是微不足道的,因此您要尽量保持保留的数量相当小。通常,您会保留较大的连续内存块,并根据需要获取更多。只要比较上面的两个例子,你就会发现在处理一个单一的预订时要做和考虑的事情明显少得多。
当然,以细粒度的方式管理内存有其优点。您可以在有限的资源下非常高效,但这也增加了复杂性。

相关问题