struct _xStringList
{
char ***list;
int size;
/*<private>*/int al;
};
В ней хранится список строк.
Есть 3 функции для создания нового списка, добавления строк и удаления всего списка.
При запуске программы, где используются данные функции вне VS всё нормально, при запуске в VS
появляется ошибка в *_x_string_list_free. Что может быть за причина?
xStringList *_x_string_list_new(void)
{
xStringList *lst = (xStringList *)x_malloc(sizeof(xStringList));
lst->list = (char ***)x_malloc(sizeof(char **) * 255);
lst->al = 255;
lst->size = 0;
return lst;
}
void x_string_list_add(xStringList *lst, int count, ...)
{
char ***tmp;
int i;
P1:
if (lst != NULL)
{
P2:
if (lst->al > lst->size)
{
int i;
va_list par;
lst->list[lst->size] = (char **)x_malloc(sizeof(char *) * count);
va_start(par, count);
for (i = 0; i < count; i++)
{
lst->list[lst->size][i] = x_strdup(va_arg(par, char *));
}
lst->list[lst->size++][i] = NULL;
va_end(par);
}
else
{
tmp = lst->list;
lst->list = (char ***)x_malloc(sizeof(char **)*(lst->al*=2));
for (i = 0; i < lst->size; i++) lst->list[i] = tmp[i];
x_free(tmp);
goto P2;
}
}
else
{
lst = x_string_list_new();
goto P1;
}
}
xStringList *_x_string_list_free(xStringList *lst)
{
int i, j;
if (lst != NULL)
{
for (i = 0; i < lst->size; i++)
{
for (j = 0; lst->list[i][j] != NULL; j++)
{
x_free(lst->list[i][j]);
}
x_free(lst->list[i]); /* Здесь ошибка!
}
x_free(lst->list);
x_free(lst);
}
return NULL;
}
Вот здесь. Три звездочки — слишком большая крепость . Сделай typedef, чтобы по крайней мере до двух сократить.
В C не нужно явно приводить void * к типу твоего указателя. Так что можно писать прямо:
xStringList *lst = x_malloc(sizeof(xStringList)); Я бы использовал calloc, malloc не обнуляет память. Да и кто за тебя будет на NULL проверять? В x_string_list_add нужно циклы явные сделать а не с помощью goto.
У него тут даже не malloc а какой-то x_alloc
И вообще, мне кажется, что программы на "чистом С" вполне могут выглядеть проще, чище и элегантней без всяких кошмариков.
Of course, the code must be complete enough to compile and link.
Re[4]: Где ошибка?
От:
Аноним
Дата:
06.02.04 09:35
Оценка:
Здравствуйте, dik o-braz, Вы писали:
DOB>
DOB>void x_string_list_add(xStringList *lst, int count, ...)
DOB>{
DOB>/* ... */
DOB> if (lst->al > lst->size)
DOB> {
DOB> int i;
DOB> va_list par;
lst->>list[lst->size] = (char **)x_malloc(sizeof(char *) * count);
DOB> va_start(par, count);
DOB> for (i = 0; i < count; i++)
DOB> {
lst->>list[lst->size][i] = x_strdup(va_arg(par, char *));
DOB> }
DOB>/* Зачем нужна вот эта строчка ? VVV */
lst->>list[lst->size++][i] = NULL;
DOB>/* Возможно, ей затирается служебная инф-я хипа */
DOB>/* И в ф-ии free все падает */
DOB> va_end(par);
DOB> }
DOB>/* ... */
DOB>}
DOB>
Именно. Я уже нашёл, но всё равно спасибо. Просто память выделяю для count элементов:
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>У него тут даже не malloc а какой-то x_alloc L_L>И вообще, мне кажется, что программы на "чистом С" вполне могут выглядеть проще, чище и элегантней без всяких кошмариков.
x_malloc : тот же malloc, но с проверкой на ошибки выделения памяти.
x_free : тот же free, но с проверкой на равенство NULL передаваемого указателя и с присваиванием этому указателю NULL :
Ну что же...
Даст ист рефакторинг!
Я постарался максимально сохранить логику автора, только сделал программу чуть более читаемой и избавился от готу.
#include <malloc.h>
#include <string.h>
#include <sys/varargs.h>
typedef char* str;
typedef str* strlst;
typedef struct _xStringList {
strlst* list;
int size;
/*<private>*/int al;
} xStringList;
void x_string_list_add(xStringList* lst, int count, ...);
xStringList* x_string_list_new()
{
xStringList *lst = (xStringList *)x_malloc(sizeof(xStringList)); //allocator's left as isif (!lst)
return NULL;
lst->list = (strlst*) x_malloc(sizeof(strlst) * 255);
if (!lst->list) {
free(lst);
return NULL;
}
lst->al = 255;
lst->size = 0;
return lst;
}
void x_string_list_add(xStringList* lst, int count, ...)
{
strlst* tmp;
va_list par;
int i;
if (!lst)
lst=x_string_list_new();
if (!lst)
return;
//logic left as is. Although you should mention, that such allocated list would be lost after
//function returns. if (lst->al <= lst->size) {
//again logic left as is. But we could consider using some form of x_realloc?
tmp = lst->list;
lst->al*=2;
lst->list = (strlst*)x_malloc(sizeof(strlst)*(lst->al));
if (!lst->list)
return;
for (i = 0; i < lst->size; ++i)
lst->list[i] = tmp[i];
x_free(tmp);
}
lst->list[lst->size] = (strlst)x_malloc(sizeof(str) * (count+1));
va_start(par, count);
for (i = 0; i < count; i++)
lst->list[lst->size][i] = x_strdup(va_arg(par, str));
lst->list[lst->size][i]=NULL;
++lst->size;
va_end(par);
}
void x_string_list_free(xStringList *lst)
{
int i, j;
if (!lst)
return;
for (i = 0; i < lst->size; i++) {
for (j = 0; lst->list[i][j]; ++j)
x_free(lst->list[i][j]);
x_free(lst->list[i]);
}
x_free(lst->list);
x_free(lst);
}
int main() {
xStringList* thelist=x_string_list_new();
x_string_list_add(thelist, 2, "one string", "another string");
x_string_list_free(thelist);
return 0;
}
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>>У него тут даже не malloc а какой-то x_alloc L_L>>И вообще, мне кажется, что программы на "чистом С" вполне могут выглядеть проще, чище и элегантней без всяких кошмариков. А>x_malloc : тот же malloc, но с проверкой на ошибки выделения памяти. А>x_free : тот же free, но с проверкой на равенство NULL передаваемого указателя и с присваиванием этому указателю NULL :
А>
assert работает только в debug версии программы, а что на счет release-а?
Re[5]: Где ошибка?
От:
Аноним
Дата:
06.02.04 10:58
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>>>У него тут даже не malloc а какой-то x_alloc L_L>>>И вообще, мне кажется, что программы на "чистом С" вполне могут выглядеть проще, чище и элегантней без всяких кошмариков. А>>x_malloc : тот же malloc, но с проверкой на ошибки выделения памяти. А>>x_free : тот же free, но с проверкой на равенство NULL передаваемого указателя и с присваиванием этому указателю NULL :
А>>
АШ>assert работает только в debug версии программы, а что на счет release-а?
А она и нужна только на время отладки программы. В крайнем случае можно определить
#define _DEBUG
код
#undef _DEBUG
А для случаев, когда неизвестно, равен ли указатель NULL по логике программы, есть easy версия функции:
void *__mem_free_easy__(void *point)
{
if (point) __STANDART_FREE__(point);
return NULL;
}
Re[2]: Где ошибка?
От:
Аноним
Дата:
06.02.04 11:04
Оценка:
Здравствуйте, Vamp, Вы писали:
V>Ну что же... V>Даст ист рефакторинг! V>Я постарался максимально сохранить логику автора, только сделал программу чуть более читаемой и избавился от готу.
V>
V>#include <malloc.h>
V>#include <string.h>
V>#include <sys/varargs.h>
V>typedef char* str;
V>typedef str* strlst;
V>typedef struct _xStringList {
V> strlst* list;
V> int size;
V> /*<private>*/
V> int al;
V>} xStringList;
V>void x_string_list_add(xStringList* lst, int count, ...);
V>xStringList* x_string_list_new()
V>{
V> xStringList *lst = (xStringList *)x_malloc(sizeof(xStringList)); //allocator's left as is
V> if (!lst)
V> return NULL;
lst->>list = (strlst*) x_malloc(sizeof(strlst) * 255);
V> if (!lst->list) {
V> free(lst);
V> return NULL;
V> }
lst->>al = 255;
lst->>size = 0;
V> return lst;
V>}
V>void x_string_list_add(xStringList* lst, int count, ...)
V>{
V> strlst* tmp;
V> va_list par;
V> int i;
V> if (!lst)
V> lst=x_string_list_new();
V> if (!lst)
V> return;
V> //logic left as is. Although you should mention, that such allocated list would be lost after
V> //function returns.
V> if (lst->al <= lst->size) {
V> //again logic left as is. But we could consider using some form of x_realloc?
V> tmp = lst->list;
lst->>al*=2;
lst->>list = (strlst*)x_malloc(sizeof(strlst)*(lst->al));
V> if (!lst->list)
V> return;
V> for (i = 0; i < lst->size; ++i)
lst->>list[i] = tmp[i];
V> x_free(tmp);
V> }
lst->>list[lst->size] = (strlst)x_malloc(sizeof(str) * (count+1));
V> va_start(par, count);
V> for (i = 0; i < count; i++)
lst->>list[lst->size][i] = x_strdup(va_arg(par, str));
lst->>list[lst->size][i]=NULL;
V> ++lst->size;
V> va_end(par);
V>}
V>void x_string_list_free(xStringList *lst)
V>{
V> int i, j;
V> if (!lst)
V> return;
V> for (i = 0; i < lst->size; i++) {
V> for (j = 0; lst->list[i][j]; ++j)
V> x_free(lst->list[i][j]);
V> x_free(lst->list[i]);
V> }
V> x_free(lst->list);
V> x_free(lst);
V>}
V>int main() {
V> xStringList* thelist=x_string_list_new();
V> x_string_list_add(thelist, 2, "one string", "another string");
V> x_string_list_free(thelist);
V> return 0;
V>}
V>
Класс! Именно так написал бы "Я" сегодняшний. Всё это дело было написано 7 лет назад, и только для фиксированного числа параметров. Сегодня понадобилось вновь, теперь для переменного.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Vamp, Вы писали:
V>>Ну что же... V>>Даст ист рефакторинг! V>>Я постарался максимально сохранить логику автора, только сделал программу чуть более читаемой и избавился от готу.
V>>
V>>#include <malloc.h>
V>>#include <string.h>
V>>#include <sys/varargs.h>
V>>typedef char* str;
V>>typedef str* strlst;
V>>typedef struct _xStringList {
V>> strlst* list;
V>> int size;
V>> /*<private>*/
V>> int al;
V>>} xStringList;
V>>void x_string_list_add(xStringList* lst, int count, ...);
V>>xStringList* x_string_list_new()
V>>{
V>> xStringList *lst = (xStringList *)x_malloc(sizeof(xStringList)); //allocator's left as is
V>> if (!lst)
V>> return NULL;
lst->>>list = (strlst*) x_malloc(sizeof(strlst) * 255);
V>> if (!lst->list) {
V>> free(lst);
V>> return NULL;
V>> }
lst->>>al = 255;
lst->>>size = 0;
V>> return lst;
V>>}
V>>void x_string_list_add(xStringList* lst, int count, ...)
V>>{
V>> strlst* tmp;
V>> va_list par;
V>> int i;
V>> if (!lst)
V>> lst=x_string_list_new();
V>> if (!lst)
V>> return;
V>> //logic left as is. Although you should mention, that such allocated list would be lost after
V>> //function returns.
V>> if (lst->al <= lst->size) {
V>> //again logic left as is. But we could consider using some form of x_realloc?
V>> tmp = lst->list;
lst->>>al*=2;
lst->>>list = (strlst*)x_malloc(sizeof(strlst)*(lst->al));
V>> if (!lst->list)
V>> return;
V>> for (i = 0; i < lst->size; ++i)
lst->>>list[i] = tmp[i];
V>> x_free(tmp);
V>> }
lst->>>list[lst->size] = (strlst)x_malloc(sizeof(str) * (count+1));
V>> va_start(par, count);
V>> for (i = 0; i < count; i++)
lst->>>list[lst->size][i] = x_strdup(va_arg(par, str));
lst->>>list[lst->size][i]=NULL;
V>> ++lst->size;
V>> va_end(par);
V>>}
V>>void x_string_list_free(xStringList *lst)
V>>{
V>> int i, j;
V>> if (!lst)
V>> return;
V>> for (i = 0; i < lst->size; i++) {
V>> for (j = 0; lst->list[i][j]; ++j)
V>> x_free(lst->list[i][j]);
V>> x_free(lst->list[i]);
V>> }
V>> x_free(lst->list);
V>> x_free(lst);
V>>}
V>>int main() {
V>> xStringList* thelist=x_string_list_new();
V>> x_string_list_add(thelist, 2, "one string", "another string");
V>> x_string_list_free(thelist);
V>> return 0;
V>>}
V>>
А>Класс! Именно так написал бы "Я" сегодняшний. Всё это дело было написано 7 лет назад, и только для фиксированного числа параметров. Сегодня понадобилось вновь, теперь для переменного.
Остановился на таком варианте: