Я отлаживал часть унаследованного кода, работающего в системе XScale (arm v5te) с linux, который воспроизводит сбои.
Я отладил с помощью gdb и установил MALLOC_CHECK_ в 1. Это многокод, так что просто некоторые фрагменты:
У нас есть такая структура:
typedef struct {
...clipped..
char **data_column_list;
/** data column count */
int data_column_cnt;
...clipped
} csv_t;
Мы инициализируем столбцы в функции, помещая их в переменную "columns"
/* 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" / config, котораясодержит эти идентификаторы.Код выше: cfg.sen_list [i] -> data_list [j] -> id;где cfg - это структура, sen_list - это массив указателей на структуры, data_list - это массив указателей на другие структуры, которые содержат строку «id».
Когда программа получает сигнал SIGUSR1, конфигурацияобновляется.Все эти структуры data_list и sen_list освобождаются, затем генерируются новые.Затем с первой функцией генерируются новые столбцы идентификаторов и помещаются в структуру 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);
Когда структуры, содержащие строки идентификаторов, освобождаются, у меня все еще есть массивы указателей с (недействительными) указателями, а не с нулевыми указателями:
(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, к сожалению, недоступен на arm v5te: (
Отлаживаю это часами и буду рада за любую помощь. Большое спасибо, Cheers, Бен
ОБНОВЛЕНИЕ:
Мне интересно, может ли это быть связано с какой-то проблемой "области видимости". В другом приложении работает практически идентичный код. Сбой функции "csv_free" используется обеими программами (статически связанными).Единственное отличие состоит в том, что структура, содержащая указатель для освобождения, объявляется и обычно определяется в рабочей программе и объявляется как external
и определяется в другом файле, отличном от main.c. Вызов «free» вручную в main.c работает, в то время как работаетвызов "csv_free" дает сбой. Загадкой мне это ...