我有一个构建字符串数组的函数(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;
}
为什么会这样?
答案 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;
}