C - Cant free char **指针内存 - 错误CrtIsValidHeapPointer

时间:2015-10-05 16:56:53

标签: c pointers memory malloc

我有一个构建字符串数组的函数(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;
}

为什么会这样?

2 个答案:

答案 0 :(得分:2)

请在creating_array中尝试

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

答案 1 :(得分:1)

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

通常在释放指针后,人们将其设置为NULL以避免混淆(因此,只要指针不为空,它就指向有效的内存)。这可以避免错误。此问题对于free(NULL)也是合法的,因此如果您双重释放地址,就不会遇到非常严重且难以调试的问题。

重要的一点是,在这种情况下,本例中的括号(*pArr)[2]很重要,要覆盖C中的运算符优先级。如果尝试*pArr[2],则假设您要取消引用指针存储在元素[2]中。 (*pArr)[2]表示元素的返回元素来自pArr指向的地址的位置。 C假设另一种情况并且在这种情况下你需要parens的原因是另一种用法更常见,所以很方便。

注意:总是检查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 - exiting\n");
        return -1;
    }
    for (size_t i = 0; i < STRING_COUNT; i++) {
        printf("%s\n", 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;

}