C -不能释放char**指针内存-错误的crtisvalidheappointment



我有一个函数,它建立一个字符串数组(char*)。
在我完成使用数组后,我想释放它的内存,但随后我得到一个CrtIsValidHeapPointer错误。

代码:

int main(int argc, char * argv[])
{
    char** arr = NULL;
    creating_array(&arr);    // Building the array
    //free each string memory
    for (size_t i = 0; i < 4; i++)
    {
        free(arr[i]);
    }
    // until here everything works fine :)
    //free the array memory    
    free(arr);        // Error CrtIsValidHeapPointer
    return 0;
}
void creating_array(char*** pArr)
{
    char** arr = (char**)malloc(4);
    arr[0] = (char*)malloc(5 * sizeof(char));
    strcpy(arr[0], "aaaa");
    arr[1] = (char*)malloc(5 * sizeof(char));
    strcpy(arr[1], "bbbb");
    arr[2] = (char*)malloc(5 * sizeof(char));
    strcpy(arr[2], "cccc");
    arr[3] = (char*)malloc(5 * sizeof(char));
    strcpy(arr[3], "dddd");
    *pArr = arr;
}

为什么会发生?

请尝试,在creating_array

char **arr ;
arr=(char **) calloc( 4 , sizeof(char *));

下面是工作代码。它现在编译并运行。

通常在释放指针后,人们将其设置为NULL以避免混淆(因此任何时候指针不为空都指向有效的内存)。这样可以避免bug。此外,free(NULL)是合法的,所以你不会陷入非常严重的和难以调试的问题,如果你双重释放一个地址。

重要的一点是,在这种情况下,括号在这种情况下(*pArr)[2]是重要的,覆盖c中的操作符优先级。如果您尝试*pArr[2],它假定您的意思是取消引用存储在元素[2]的指针。(*pArr)[2]表示从pArr所指向的地址返回元素。C假设另一种情况,并且在这种情况下需要parent的原因是另一种用法更常见,所以更方便。

注意:总是检查malloc()和函数调用的返回值,并有捕获和记录错误的策略。否则,当你开始编写更大的程序时,你会发现它们极其困难、麻烦或几乎不可能调试。

另一件事是创建命名常量而不是字面量,因为这样可以清楚地知道数字是什么以及如何使用它,如果在多个地方需要该数字,则可以在一个地方更改它。它使程序更容易阅读和理解。

#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#define STRING_COUNT 4
char **create_array(char ***pArr);
int 
main()
{
    char **arr = NULL;
    if (create_array(&arr) == NULL) {
        fprintf(stderr, "out of memory - exitingn");
        return -1;
    }
    for (size_t i = 0; i < STRING_COUNT; i++) {
        printf("%sn", arr[i]);
    }
    for (size_t i = 0; i < STRING_COUNT; i++) {
        free(arr[i]);
        arr[i] = NULL;
    }
    free(arr);      
    return 0;
}
char **
create_array(char ***pArr)
{
    if ((*pArr = malloc(STRING_COUNT * sizeof (char **))) == NULL) {
       return NULL;
    }
    if (((*pArr)[0] = strdup("aaaa")) == NULL) {
        return NULL;
    }
    if (((*pArr)[1] = strdup("bbbb")) == NULL) {
        free((*pArr)[0]);
        *pArr[0] = NULL;
        return NULL;
    }
    if (((*pArr)[2] = strdup("bbbb")) == NULL) {
        free((*pArr)[0]);
        *pArr[0] = NULL;
        free((*pArr)[1]);
        *pArr[1] = NULL;
        return NULL;
    }
    if (((*pArr)[3]= strdup("bbbb")) == NULL) {
        free((*pArr)[0]);
        *pArr[0] = NULL;
        free((*pArr)[2]);
        *pArr[1] = NULL;
        free((*pArr)[2]);
        *pArr[2] = NULL;
        return NULL;
    }
    return *pArr;
}

最新更新