如何释放分配给三指针的内存



嗨,我想释放分配的内存,使用malloc:分配如下

```
int ret = 0;
int nrow = 0, ncol = 0, i = 0, j = 0, count = 0;
char *err_messg;
char **result;
char ***recordset;
ResultSet resultSet_Table;
char RET[10];
char sql_string[QUERY_BUFF_SIZE]; //this honestly needs to be more elegant; will do for now
va_list args;
va_start(args, fmt);
sql_string[0] = '';
printf("Temp called 3n");
ret = vsprintf(sql_string, fmt, args);
printf("Temp called 4n");
va_end(args);
printf("n%sn", sql_string);
//initialize resultSet_Table;
resultSet_Table.rows = 0;
resultSet_Table.cols = 0;
resultSet_Table.recordset = NULL;
//        if(sqlite3_open("/home/ap/pub/CONFIG.DB", &StructSql) == SQLITE_OK)
//        {
printf("Database Openedn");
// CTOS_LCDTPrintXY(1, 1, "DB Opened");

ret = sqlite3_get_table(
StructSql,
sql_string,
&result,
&nrow,
&ncol,
&err_messg
);
printf("nrow=%d ncol=%dn", nrow, ncol);
char*** recordset = (char ***) malloc(nrow * sizeof (char **));

for (count = ncol; count < ((nrow + 1) * ncol); count++) {

printf("Enter in LOOPn");
recordset[i] = (char **) malloc(ncol * sizeof (char *));
for (j = 0; j < ncol; j++) 
{
printf("%s ", result[count]);
recordset[i][j] = (char *) malloc((strlen(result[count]) + 1));
strcpy(recordset[i][j], result[count]);

if (j != (ncol - 1))
count++;
}
i++;
printf("n");
}
```

我想释放这个内存,但如何使用free((。我试着如下释放它:

int i = 0;

for (count = ncol; count < ((nrow + 1) * ncol); count++) {

printf("Enter in LOOPn");

for (j = 0; j < ncol; j++) {
free(recordset[i][j]);

if (j != (ncol - 1))
count++;
}
free(recordset[i]); 
i++;
printf("n");
}

free(recordset);

当我写这段代码时,我的程序开始崩溃。有人能帮我纠正我在这段代码中写错的地方吗?

实际上为sqlite3_get_table((结果分配了内存。内存分配是成功完成的,但当我试图释放它时,它就产生了问题。

一般来说,对于每个对malloc()的调用,都必须有一个匹配的调用free()。您需要或多或少地按照与分配顺序相反的顺序释放内存(因此free(recordset)确实应该是最后一个(。

您的内存分配代码已损坏。释放内存的代码也同样被破坏了。

根据注释,您有nrows + 1行数据,每行都包含ncols个值,每个值都是以null结尾的字符串。目前尚不清楚您是否必须从results复制信息,但它确实确保了内存完全在您的控制之下。

你没有展示你的大部分变量声明——这总是让那些愿意帮助你的人的生活变得不必要的艰难。

下面的代码省略了对内存分配失败的检查。您不应该忽略这些,但在分配失败时释放已经分配的空间会变得很麻烦。

你应该有一个大致如下的功能:

char ***array_to_recordset(size_t nrows, size_t ncols, char *results[])
{
char ***recordset = malloc((nrows + 1) * sizeof(*recordset));
size_t count = 0;
for (size_t i = 0; i < nrows + 1; i++)
{
recordset[i] = malloc(ncols * sizeof(recordset[0][0]));
for (size_t j = 0; j < ncols; j++)
{
//recordset[i][j] = strdup(results[count++];
recordset[i][j] = malloc(strlen(results[count]) + 1);
strcpy(recordset[i][j], results[count++]);
}
}
return recordset;
}

然后您的发布代码变为:

void free_recordset(size_t nrows, size_t ncols, char ***recordset)
{
for (size_t i = 0; i < nrows + 1; i++)
{
for (size_t j = 0; j < ncols; j++)
free(recordset[i][j]);
free(recordset[i]);
}
free(recordset);
}

在最初发布之前,没有就此代码的有效性咨询任何编译器。它可能有错误(除了没有检查内存分配之外(——事实上,有两个打字错误阻止了它的编译(countercount,以及缺少一个右括号(

测试线束中的代码

/* SO 7140-4900 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char ***array_to_recordset(size_t nrows, size_t ncols, char *results[])
{
char ***recordset = malloc((nrows + 1) * sizeof(*recordset));
size_t count = 0;
for (size_t i = 0; i < nrows + 1; i++)
{
recordset[i] = malloc(ncols * sizeof(recordset[0][0]));
for (size_t j = 0; j < ncols; j++)
{
//recordset[i][j] = strdup(results[count++];
recordset[i][j] = malloc(strlen(results[count]) + 1);
strcpy(recordset[i][j], results[count++]);
}
}
return recordset;
}
static void free_recordset(size_t nrows, size_t ncols, char ***recordset)
{
for (size_t i = 0; i < nrows + 1; i++)
{
for (size_t j = 0; j < ncols; j++)
free(recordset[i][j]);
free(recordset[i]);
}
free(recordset);
}
// Test Harness
static size_t max_string_width(size_t nrows, size_t ncols, char ***recordset)
{
size_t maxwid = 0;
for (size_t i = 0; i < nrows + 1; i++)
{
for (size_t j = 0; j < ncols; j++)
{
size_t length = strlen(recordset[i][j]);
if (length > maxwid)
maxwid = length;
}
}
return maxwid;
}
static void dump_recordset(size_t nrows, size_t ncols, char ***recordset)
{
int maxwid = max_string_width(nrows, ncols, recordset);
for (size_t i = 0; i < nrows + 1; i++)
{
const char *pad = "";
for (size_t j = 0; j < ncols; j++)
{
printf("%s%-*s", pad, maxwid, recordset[i][j]);
pad = "  ";
}
putchar('n');
}
}
int main(void)
{
char *results[] =
{
"Name",  "Number",
/* random -n 4 -T '%W%v%c%v%c %[10:99]d' | commalist -S -q '"' -B 8 */
"Caqam", "18",
"Cepay", "38",
"Jojaj", "43",
"Tovun", "59",
};
enum { NUM_ROWS = 4, NUM_COLS = 2 };
char ***recordset = array_to_recordset(NUM_ROWS, NUM_COLS, results);
dump_recordset(NUM_ROWS, NUM_COLS, recordset);
free_recordset(NUM_ROWS, NUM_COLS, recordset);
return 0;
}

输出

Name    Number
Caqam   18    
Cepay   38    
Jojaj   43    
Tovun   59 

macOS上的leaks程序没有报告泄漏,当macOSmalloc()代码配置为测试内存滥用时,也没有报告内存滥用。

测试分配失败并从中恢复

该代码变体包括函数xmalloc(),该函数可以被配置为在给定数量的分配之后开始失败。然后,代码在1..30个分配之后测试故障路径(无论如何只有16个分配(。它也没有泄漏和内存滥用。

/* SO 7140-4900 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Generate allocation failures */
static size_t counter = 0;
static size_t failure = 0;
static void *xmalloc(size_t size)
{
if (failure > 0 && ++counter >= failure)
{
fprintf(stderr, "%s() failed (counter = %zu, failure = %zu)n", __func__, counter, failure);
return NULL;
}
return malloc(size);
}
static char ***array_to_recordset(size_t nrows, size_t ncols, char *results[])
{
char ***recordset = xmalloc((nrows + 1) * sizeof(*recordset));
if (recordset == NULL)
return NULL;
size_t count = 0;
for (size_t i = 0; i < nrows + 1; i++)
{
recordset[i] = xmalloc(ncols * sizeof(recordset[0][0]));
if (recordset[i] == NULL)
{
for (size_t ei = 0; ei < i; ei++)
{
for (size_t ej = 0; ej < ncols; ej++)
free(recordset[ei][ej]);
free(recordset[ei]);
}
free(recordset);
return NULL;
}
for (size_t j = 0; j < ncols; j++)
{
//recordset[i][j] = strdup(results[count++];
recordset[i][j] = xmalloc(strlen(results[count]) + 1);
if (recordset[i][j] == NULL)
{
for (size_t ej = 0; ej < j; ej++)
free(recordset[i][ej]);
free(recordset[i]);
for (size_t ei = 0; ei < i; ei++)
{
for (size_t ej = 0; ej < ncols; ej++)
free(recordset[ei][ej]);
free(recordset[ei]);
}
free(recordset);
return NULL;
}
strcpy(recordset[i][j], results[count++]);
}
}
return recordset;
}
static void free_recordset(size_t nrows, size_t ncols, char ***recordset)
{
for (size_t i = 0; i < nrows + 1; i++)
{
for (size_t j = 0; j < ncols; j++)
free(recordset[i][j]);
free(recordset[i]);
}
free(recordset);
}
static size_t max_string_width(size_t nrows, size_t ncols, char ***recordset)
{
size_t maxwid = 0;
for (size_t i = 0; i < nrows + 1; i++)
{
for (size_t j = 0; j < ncols; j++)
{
size_t length = strlen(recordset[i][j]);
if (length > maxwid)
maxwid = length;
}
}
return maxwid;
}
static void dump_recordset(size_t nrows, size_t ncols, char ***recordset)
{
int maxwid = max_string_width(nrows, ncols, recordset);
for (size_t i = 0; i < nrows + 1; i++)
{
const char *pad = "";
for (size_t j = 0; j < ncols; j++)
{
printf("%s%-*s", pad, maxwid, recordset[i][j]);
pad = "  ";
}
putchar('n');
}
}
int main(void)
{
char *results[] =
{
"Name",  "Number",
/* random -n 4 -T '%W%v%c%v%c %[10:99]d' | commalist -S -q '"' -B 8 */
"Caqam", "18",
"Cepay", "38",
"Jojaj", "43",
"Tovun", "59",
};
enum { NUM_ROWS = 4, NUM_COLS = 2 };
for (failure = 0; failure < 30; failure++)
{
counter = 0;
char ***recordset = array_to_recordset(NUM_ROWS, NUM_COLS, results);
if (recordset != NULL)
{
dump_recordset(NUM_ROWS, NUM_COLS, recordset);
free_recordset(NUM_ROWS, NUM_COLS, recordset);
}
}
return 0;
}

请注意,在分配失败后释放内存的代码必须处理部分分配的行、以前完全分配的行,当然还有初始分配。

输出

Name    Number
Caqam   18    
Cepay   38    
Jojaj   43    
Tovun   59    
xmalloc() failed (counter = 1, failure = 1)
xmalloc() failed (counter = 2, failure = 2)
xmalloc() failed (counter = 3, failure = 3)
xmalloc() failed (counter = 4, failure = 4)
xmalloc() failed (counter = 5, failure = 5)
xmalloc() failed (counter = 6, failure = 6)
xmalloc() failed (counter = 7, failure = 7)
xmalloc() failed (counter = 8, failure = 8)
xmalloc() failed (counter = 9, failure = 9)
xmalloc() failed (counter = 10, failure = 10)
xmalloc() failed (counter = 11, failure = 11)
xmalloc() failed (counter = 12, failure = 12)
xmalloc() failed (counter = 13, failure = 13)
xmalloc() failed (counter = 14, failure = 14)
xmalloc() failed (counter = 15, failure = 15)
xmalloc() failed (counter = 16, failure = 16)
Name    Number
Caqam   18    
Cepay   38    
Jojaj   43    
Tovun   59    
…

当由于内存分配不足而没有发生分配失败时,输出将重新出现。

最新更新