LINUX.ORG.RU

Проблема с выделением памяти C


0

0

Господа, ниже представлена рекурсивная функция для добавления нового элемента в конец списка. Категорически отказывается работать (segfault), когда список не инициализирован, хотя соответствующий блок присутствует в функции.

...
list_t list = NULL;
...

void addtolist_r(list_t* mylist, const int value)
{
if( mylist == NULL ){
printf("addtolist_r entry\n");
printf("debug entry value = %d\n", value);
mylist = (list_t *)malloc(sizeof(mylist));

mylist->value = value;
mylist->next = NULL;

return;
}

if( mylist->next ) addtolist_r(mylist->next, value);
else
{
list_t* temp = (list_t *)malloc(sizeof(list_t));

temp->value = value;
temp->next = NULL;

mylist->next = temp;
}
}

...
addtolist_r(list, 42); // Не добавит, и не инициализирует список.
...

Хотя, если проинициализировать вручную, то все работает как надо. Подскажите плз. где здесь ошибка, и как ее правильно исправить? Предполагаю, что просто не выделяется память. Но почему?

Заранее спасибо.

anonymous

для таких случаев есть gdb:)

anonymous
()

потому, что в C параметры функции передаются по значению. и list после вызова addtolist_r(list, 42) остается прежним.

есть как минимум 3 способа исправления:
- сделать инициализацию списка отдельной функцией.
- передавать в функцию addtolist_r указатель на указатель.
- возвращать из функции (изменившийся в случае инициализации) указатель mylist.

hatefu1_dead
()

Ошибка в том, что переменные в аргументах C функций не изменяются.
Вот работающий вариант программы:

#include <stdio.h>
#include <stdlib.h>

struct list_t {
	int		value;
	struct list_t	*next;
};

void addtolist_r(struct list_t **mylist, const int value)
{
	if (*mylist == NULL) {
		*mylist = malloc(sizeof(struct list_t));

		(*mylist)->value = value;
		(*mylist)->next = NULL;

		return;
	}

	if ((*mylist)->next) {
		addtolist_r(&(*mylist)->next, value);
	} else {
		struct list_t *temp = malloc(sizeof(struct list_t));

		temp->value = value;
		temp->next = NULL;

		(*mylist)->next = temp;
	}
}

void print_list(struct list_t *list)
{
	if (list != NULL) {
		printf("%d\n", list->value);
		print_list(list->next);
	}
}

int main(void)
{
	struct list_t *mylist = NULL;

	addtolist_r(&mylist, 1);
	addtolist_r(&mylist, 2);
	addtolist_r(&mylist, 3);

	print_list(mylist);

	return 0;
}

Если же используется C++, то вместо указателя на указатель можно воспользоваться ссылкой на указатель, что удобнее.

bbk123 ★★★★★
()
Ответ на: комментарий от bbk123

Благодарю за помощь. Просто считал, что раз передается указатель, то его можно легко и беспроблемно изменять.

anonymous
()
Ответ на: комментарий от anonymous

Макросы из sys/queue.h не стандартизированы. Лучше использовать insque(3) и remque(3).

bbk123 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.