вернуть указатель на массив указателей - PullRequest
1 голос
/ 04 июля 2010

У меня проблемы с освобождением указателя в массиве указателей (значения).

typedef struct MyStruct{  char** values;  }MyStruct;

В C я создаю динамический массив.

JSDictionary **array = (JSDictionary **)malloc(sizeof(JSDictionary *) * numRows);

resultSet должен быть массивом указателей JSDictionary. Я создаю структуру как:

JSDictionary * newJSDictionaryWithSize(unsigned int size)

{
JSDictionary *new = malloc(sizeof(JSDictionary));
    printf("new %p\n", self);
new->_size = size;
new->count = 0;

new->values = (char **) malloc(sizeof(char *) * size);
for(unsigned int i = 0; i < size; i++){
    new->values[i] = (char *)malloc(sizeof(char *));
}

return new;
}

Все создает и работает нормально. Это бесплатно, что доставляет мне проблемы.

void deallocJSDictionary(struct JSDictionary *self)

{
printf("dealloc %p\n", self);
for(unsigned int i = 0; i < self->_size; i++){
    printf("free %p\n", &self->values[i]);
    free(self->values[i]);
}
free(self->values);
free(self);

}

Я получаю освобождаемый указатель, ошибка не выделяется. Передаваемый указатель показывает тот же адрес памяти, что и тот, который я создал и добавил в массив. Указатель значений (в отладчике) показывает тот же адрес памяти в функции dealloc, что и при создании. Проблема заключается в попытке освободить первую точку в массиве значений. Любые идеи, почему первая точка в массиве указателя значений отличается?

Ответы [ 3 ]

4 голосов
/ 04 июля 2010

Я вижу две проблемы до сих пор. Во-первых:

new->values[i] = (char *)malloc(sizeof(char *));

Эта строка выделяет одиночный указатель - вероятно, не то, что вы хотите. Скорее всего, должно быть что-то вроде:

new->values[i] = malloc( MAX_SIZE_OF_VALUE );

т.е. буфер для хранения значения. Вы также можете выделить один большой патрон, чтобы сохранить все значения и просто сместить в эту память.

Второе:

printf("free %p\n", &self->values[i]);
free(self->values[i]);

Это печатает и пытается free(3) два разных указателя. Первый - это адрес второго.

Что касается фактической ошибки освобождения - у вас есть подобные назначения в коде, управляющем словарем?

dict->values[i] = some_value;

Если это так - вы переопределяете указатели на (и просачиваетесь) выделенную память с помощью указателей на, вероятно, стек или статическую память. Вы должны скопировать значение в "буфер значений". Что-то вроде:

strlcpy( dict->values[i], some_value, MAX_SIZE_OF_VALUE );

Надеюсь, это поможет.

1 голос
/ 04 июля 2010

Нет ничего плохого в ваших функциях. Они хорошо компилируются, хотя и после нескольких синтаксических ошибок, и выдают результат, как и ожидалось. Как уже отмечали другие, вы, возможно, присваиваете выделенные указатели, данные, которые не были выделены (т.е. данные стека), или вы передаете JSDictionary структуры, которые не были должным образом распределены в первую очередь через newJSDictionaryWithSize.

В качестве быстрого теста выполните alloc / dealloc только на одном JSDictionary, чтобы убедиться, что ваши функции работают.

JSDictionary *ptr = newJSDictionaryWithSize(10);
deallocJSDictionary(ptr);
1 голос
/ 04 июля 2010

Проблема, вероятно, в вашем коде выделения памяти.Следующая строка

new->values = (char **) malloc(sizeof(char *) * size);

выделяет массив из char указателей, содержащих size элементов.Следовательно, в этом нет необходимости:

for(unsigned int i = 0; i < size; i++){
    new->values[i] = (char *)malloc(sizeof(char *));
}

То, что вы здесь делаете, - это сохранение char ** приведения к char * в каждом элементе массива new->values.То есть вы выделяете достаточно памяти для хранения значения char *, а затем сохраняете указатель на эту память в массиве new->values.Я предполагаю, что вы сделали это по ошибке, потому что

new->values = (char **) malloc(sizeof(char *) * size);

уже выделил достаточно памяти для каждого элемента массива new->values.

Я предполагаю, что вы хотите:

for(unsigned int i = 0; i < size; i++){
    new->values[i] = (char *)malloc(sizeof(char) * MAX_STRING_LENTH);
}

для создания буфера char из MAX_STRING_LENGTH элементов для каждого элемента массива new->values.Это позволяет вам хранить строку в каждом элементе, и ваш free код должен работать нормально.

В качестве альтернативы, если элементы new->values установлены где-то еще, то вы, вероятно, не хотитебыть free их в вашем деконструкторе, если только они не были распределены динамически, и вы не знаете, что других ссылок на них в этот момент не существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...