LINUX.ORG.RU

ошибка зеленого в си


0

0

привет, недавно начал постигать си. язык нравиться (да да, по началу конечно болело кое что без ооп, но потом понял всю мощь указателей).

Вызывается вот такой код ошибки при компиляции:

PS C:\DJGPP\bin> .\gcc.exe D:\Projects\c\linked_list_2.c; C:\DJGPP\bin\a.exe
lea
lea
Exiting due to signal SIGSEGV
General Protection Fault at eip=00003f33
eax=3d230065 ebx=3d230065 ecx=00000000 edx=00000000 esi=00000054 edi=0000ff3
ebp=010eff88 esp=010eff84 program=C:\DJGPP\BIN\A.EXE
cs: sel=01a7  base=01140000  limit=010effff
ds: sel=01af  base=01140000  limit=010effff
es: sel=01af  base=01140000  limit=010effff
fs: sel=017f  base=000059d0  limit=0000ffff
gs: sel=01bf  base=00000000  limit=0010ffff
ss: sel=01af  base=01140000  limit=010effff
App stack: [010f0000..01070000]  Exceptn stack: [0000fe9c..0000df5c]

после ручного дебага (лол) понял, что ошибка в функции:

int Llist_child_is_exists(Llist* base_list)

сама программа:

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

struct linked_list {
	char* value;
	struct linked_list* next;
};

typedef struct linked_list Llist;

Llist* Llist_new(void) {
	Llist* ptr;
	ptr = malloc(sizeof(Llist));
	return ptr;
}

Llist* Llist_append(Llist* base_list) {
	Llist* new;
	new = malloc(sizeof(Llist));
	base_list -> next = new;
	return new;
}

int Llist_child_is_exists(Llist* base_list) {
	printf("%s\n",base_list -> value);
	return 1;
}

int main(void) 
{
	Llist* list_a = Llist_new();
	Llist* list_b = Llist_append(list_a);
	list_b -> value = (char*) "lea";
	printf("%s\n",list_b -> value);
	printf("%s\n",list_a -> next -> value);
	int result = Llist_child_is_exists(list_a);
	printf("%i\n",result);
}

вроде бы в качестве аргумента функция принимает указатель на структуру Llist ... наверное я где-то ступил. Это можно сказать первая попытка реализовать linked_list на си ... (да и вообще)

Заранее вам благодарен.


У тебя в list_a->value мусор. Ты его ничем не инициализируешь.

Совет... Сделай добавление либо в конец списка, либо в начало. А не так как сейчас — к элементу. Если в конец списка, то new->next = 0x0, а next у _последнего_ элемента в списке = new. Если в начало, то new->next = base.

Удачи!

ien
()

> язык нравиться

Лучше бы тебе русский вместо Си нравился.

Sphinx ★★☆☆
()

так, первое правило начинающего джедая: при входе в функцию сразу проверять все указатели которые планируются к использованию на NULL

int Llist_child_is_exists(Llist* base_list) {

   if(!base_list) {
       return -1;
   }

   printf("%s\n",base_list -> value); 
   return 1; 
} 
shty ★★★★★
()
Ответ на: комментарий от ien

>Сделай добавление либо в конец списка, либо в начало. А не так как сейчас — к элементу.

В GLib и Линукс-ядре сделано именно так.

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

теперь я понял это =) указатели для меня новы и все подводные камни пока еще не известны.

ciss
() автор топика

по теме: value у тебя указатель и ты его нигде не инитишь, поэтому и сегфолтишься при попытке поиспользовать его

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

Лучше assert вместо return -1, NULL в указателе - это ошибка программиста, и не runtime-error.

в некоторых случаях - согласен, но когда пишешь либу/кусок кода которой/которым непонятно кто пользоваться будет - можно и оставить :)

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

ого оО оно у меня работет на вин7.

все беды из-за того, что интернет у меня - GRPS'ый, поэтому ничего «тяжелого» я не качаю. DJGPP -> показался легким.

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