我一直在调试一个遗留代码,运行在Linux上的XScale(arm v5te)系统,可重现崩溃。免费()无效指针 - 释放指针阵列失败
我已经用gdb调试和设置MALLOC_CHECK_为1。这是一个很大的代码,所以只是一些片段:
我们有这样的结构:
typedef struct {
...clipped..
char **data_column_list;
/** data column count */
int data_column_cnt;
...clipped
} csv_t;
我们初始化函数列,把它们放在一个变量“列”
/* Allocating memory for pointer to every register id */
columns = (char **) malloc(column_cnt * sizeof(char *));
column_cnt = 0;
/* loop over all sensors */
for(i=0; i<cfg.sen_cnt; i++) {
/* loop over all registers */
for(j=0; j<cfg.sen_list[i]->data_cnt; j++) {
/* Storing all the pointers to id */
columns[column_cnt++] = cfg.sen_list[i]->data_list[j]->id;
}
}
在另一个功能,会发生什么情况是这样的:
/* free the previous list */
csv_free(lc_csv);
lc_csv->data_column_list = columns;
lc_csv->data_column_cnt = column_cnt;
csv_free之中:
void csv_free(csv_t *csv) {
if(csv->data_column_cnt > 0)
free(csv->data_column_list);
csv->data_column_cnt = 0;
}
现在,还有另外一个功能,构建整个 “CFG”/配置结构,包含这些ID。 上面的代码:cfg.sen_list [i] - > data_list [j] - > id;其中cfg是一个结构体,sen_list是一个指向结构体的指针数组,data_list是指向其他结构体的指针数组,它包含一个字符串“id”。
当程序获得SIGUSR1信号时,配置正在更新。所有这些data_list和sen_list结构都被释放,然后生成新的结构。 然后使用第一个函数,生成新的id列,并将其放入csv结构中,但之前释放旧列表。
这就是它崩溃的地方。在csv_free中。
*** glibc detected *** /root/elv: free(): invalid pointer: 0x0001ae88 ***
我以为它应该是这样的。你有一个指针数组。当你释放指针时,你必须释放指针,指向一组指针(数组)。 或把代码而言,上述情况应模拟到:
char **ar = malloc(n * sizeof(char *));
char *xn = malloc(10 * sizeof(char)); // Do for 0 to n strings
...
ar[n] = xn; // Do for 0 to n strings
...do stuff...
free(xn); // Do for 0 to n strings
free(ar);
当结构,包含ID字符串,被释放,我仍然有我的(无效)的指针,而不是空指针的指针数组:
(gdb) p csv
$40 = {sysid = 222, ip = '\0' <repeats 49 times>,
module = "elv_v2", '\0' <repeats 14 times>, format_type = 1, msg_id = 0,
data_column_list = 0x1ae88, data_column_cnt = 10, pub_int = 30,
line_cnt = 0, pub_seq = -1, format = 0x18260}
(gdb) p csv.data_column_list[0]
$41 = 0x1b378 "0"
但我得到上面的错误消息(或SIGABRT没有MALLOC_CHECK_)。 我完全不明白这一点。我必须释放这个指针数组,否则它会变成内存泄漏。之前没有其他的免费电话,我可以找到。我不知道为什么csv.data_column_list被认为是无效指针。 Valgrind是不幸的是没有availiable上支持ARM v5TE :(
已经调试这几个小时,并乐意的任何帮助 非常感谢你, 干杯, 本
更新:
我想知道它是否可以连接到一些“范围”问题。在另一个应用程序中有几乎相同的代码,它的工作原理是崩溃的函数“csv_free”被两个程序使用(静态链接)。唯一的区别是,包含要释放的指针的结构通常在工作程序中声明和定义,并声明为external
并在除main.c之外的其他文件中定义。 在main.c工作中手动调用“free” “csv_free”崩溃。谜语我这个......
您是否尝试用valgrind运行它? – 2012-03-16 15:23:13
如果你在mallocs之后,并且在释放之前断点,那么所有的指针值是否匹配? – 2012-03-16 15:43:51
你应该检查'csv'是'NULL'还是不在'csv_free'中,并且释放'csv'后将它赋值为NULL。当'csv'为NULL或一些垃圾时,这将保护你免于'csv-> member'。 – phoxis 2012-03-16 15:57:37