C Указатель и распределение памяти: массивы Realloc и прохождение указателя
1243 просмотра
5 ответа
Для тех, кто имеет опыт работы с C, это будет простая проблема выделения / обращения к памяти:
Вот мои структуры данных:
struct configsection {
char *name;
unsigned int numopts;
configoption *options;
};
typedef struct configsection configsection;
struct configfile {
unsigned int numsections;
configsection *sections;
};
typedef struct configfile configfile;
Вот мои процедуры для инициализации раздела конфигурации или файла конфигурации и для добавления раздела конфигурации в файл конфигурации:
// Initialize a configfile structure (0 sections)
void init_file(configfile *cf) {
cf = malloc(sizeof(configfile));
cf->numsections = 0;
}
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
// Add a section to a configfile
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
cf->numsections = cf->numsections + 1;
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*cf->numsections);
// Insert the new item
cf->sections[cf->numsections] = *sec;
}
Я считаю, что моя проблема возникает в моей функции init_sec (). Вот пример:
int main(void) {
// Initialize test configfile
configfile *cf;
init_file(cf);
// Initialize test configsections
configsection *testcs1;
init_sec(testcs1, "Test Section 1");
// Try printing the value that should have just been stored
printf("test name = %s\n", testcs1->name);
Несмотря на то, что printf()
in init_sec()
успешно печатает имя, которое я только что сохранил в разделе конфигурации, попытка того же самого в printf()
of main()
вызывает ошибку сегментации. Далее addsec()
выдает ошибку сегментации.
Ответы (5)
2 плюса
Эта рутина должна быть
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
(*cf)->sections = NULL; // You forgot to initialise this.
}
т.е. вызывается init_file(&myconfigfilepointer);
так, malloc
возвращаемое значение передается обратно.
Нужно сделать такой же трюк для init_sec
Эта функция неверна - здесь исправленная версия
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*(1 + cf->numsections));
// Insert the new item
cf->sections[cf->numsections] = *sec; // Since arrays start at 0
cf->numsections = cf->numsections + 1;
}
Затем вам нужно настроить вызовы в main
2 плюса
Вы ни в коем случае не инициализируете cf->sections
, что означает, что при realloc
первой попытке вы пропускаете мусор. Добавление:
cf->sections = NULL;
чтобы init_file
помочь.
Вы также не проверяете коды возврата, но знаете, что да?
Автор: Tim Размещён: 25.02.2012 11:431 плюс
Вам нужно передать указатель значения, которое будет обновлено ... например:
// Initialize a configfile structure (0 sections)
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
}
configfile *var;
init_file(&var);
printf("%d\n", var->numsections);
В противном случае вы просто обновляете локальный указатель * cf, а не оригинал, переданный в значении
Автор: Geoffrey Размещён: 25.02.2012 11:381 плюс
Вам нужно по-настоящему переосмыслить, как аргументы функции передаются в C и каковы указатели. Ваша проблема не имеет ничего общего с распределением памяти. Скорее, ваш код назначает указатель динамически распределенной памяти только на локальную переменную , о которой вызывающий код ничего не знает.
Хотя вы можете решить проблему, передав указатель на указатель вызывающей стороны (то есть двойной указатель), это не обязательно самый элегантный или самый обычный способ обработки вещей. Скорее, вы должны вернуть результат выделения из функции. Пока вы работаете над этим, вы также calloc
должны сразу обнулять память. Завершение всего этого:
typedef struct substuff_
{
int a;
double b;
} substuff;
typedef struct stuff_
{
unsigned int n;
substuff * data;
} stuff;
substuff * init_substuff()
{
substuff * const p = malloc(sizeof *p);
if (p) { p->a = 5; p->b = -0.5; }
return p;
}
stuff * init_stuff()
{
substuff * const p = init_substuff();
if (!p) return NULL;
stuff * const q = malloc(sizeof *q);
if (q) { q->n = 10; q->data = p; }
return q;
}
В качестве упражнения вы должны написать соответствующие функции void free_substuff(substuff *)
и void free_stuff(stuff *)
.
1 плюс
Да, есть проблема в init_sec
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
Вы просто копируете указатель имени здесь, что означает, что он указывает на оригинальное хранилище имени. Если бы вы позвонили init_sec
так
configsection foobar()
{
configsection sec;
char name[80];
get_name(name);
init_sec(sec, name);
return sec;
}
name
Указатель стал недействительным момент foobar
вернулся. Вам нужно продублировать строку и сохранить вашу личную копию. В init_sec
:
sec->name = strdup(name);
Но это еще не все. В самой первой строке init_sec
вы перезаписываете указатель, который был передан указателю init_sec
malloc. Таким образом, новый указатель никогда не передается обратно в вызов. Либо используйте указатель на указатель, вообще не берите указатель configsection (в конце концов, вы выделяете), а просто возвращайте выделенный указатель: Завершите исправленную функцию:
// Initialize a configsection structure with a name (and 0 options)
configsection* init_sec(char *name) {
configsection *sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
return sec;
}
Автор: datenwolf
Размещён: 25.02.2012 11:53
Вопросы из категории :
- c Как вы форматируете unsigned long long int, используя printf?
- c What are the barriers to understanding pointers and what can be done to overcome them?
- c Как реализовать продолжения?
- c Как вы передаете функцию в качестве параметра в C?
- c Как получить список каталогов в C?
- pointers Regular cast vs. static_cast vs. dynamic_cast
- pointers Каковы различия между переменной-указателем и ссылочной переменной в C ++?
- pointers Почему я не могу конвертировать 'char **' в 'const char * const *' в C?
- memory-management Setting Objects to Null/Nothing after use in .NET
- memory-management Как работает пул автозапуска NSAutoreleasePool?
- memory-management Что и где находится стек и куча?
- memory-management Как имитировать ошибки выделения памяти
- memory-management Что такого плохого в использовании GC.Collect ()?
- reference Есть ли разница между "==" и "есть"?
- reference Определение манифеста обнаруженной сборки не соответствует ссылке на сборку
- reference Есть ли ошибки, использующие varargs с опорными параметрами
- reference Рекомендации для хорошего справочника vi?