Segmentation Fault

0

Przepisywałem listę z Pascala na C i w pewnym miejscu pojawił się Segmentation Fault

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

#define NULO NULL



typedef int tDato;
typedef struct tNodo* tPosL;
struct tNodo
{
    tDato dato;
    tPosL sig;
};
typedef struct tNodo tNodo;
typedef  tPosL tLista;

void CrearLista(tLista*);
int EsListaVacia(tLista);
tPosL Primera(tLista);
tPosL Siguiente(tLista,tPosL);
tPosL Ultima(tLista);
tPosL Anterior(tLista,tPosL);
tDato ObtenerDato(tLista,tPosL);
tPosL BuscarDato(tLista,tDato);
tPosL BuscarDatoOrdenado(tLista,tDato);
int InsertarDatoPrimera(tLista*,tDato);
int InsertarDatoUltima(tLista*,tDato);
int InsertarDatoPosicion(tLista*,tDato,tPosL);
int InsertarDatoOrdenado(tLista*,tDato);
tDato EliminarPosicion(tLista*,tPosL);
void EliminarLista(tLista*);


void MostrarLista(tLista L)
{
    tPosL P;
    P=Primera(L);
    while(P!=NULO)
    {
        printf("%d",ObtenerDato(L,P));
        P=Siguiente(L,P);
    }
    printf("\n");
}

int main()
{
    tLista lista;
    int i,n;
    CrearLista(&lista);
     srand(time(NULO));
    n=0;
   for(i=1; i<=10; i++)
    {
      while(BuscarDato(lista,n)!=NULO) 
      n=rand()%10;
        printf("Insertando %d\n",n);
        InsertarDatoOrdenado(&lista,n);
        MostrarLista(lista);
    }
    EliminarLista(&lista);
    do
    {
    }
    while(!kbhit());
    return 0;

}

void CrearLista(tLista* L)
{
    L=NULO;
}

int EsListaVacia(tLista L)
{
    return (L==NULO);
}

tPosL Primera(tLista L)
{
    return L;
}

tPosL Siguiente(tLista L,tPosL P)
{
      
    return (P->sig);
}

tPosL Ultima(tLista L)
{
    tPosL pos;
    pos=Primera(L);
    while(Siguiente(L,pos)!=NULO) pos=Siguiente(L,pos);
    return pos;
}

tPosL Anterior(tLista L,tPosL P)
{
    tPosL pos;
    pos=Primera(L);
    while((pos!=NULO)&&(Siguiente(L,pos)!=P)) pos=Siguiente(L,pos);
    return pos;
}

tDato ObtenerDato(tLista L,tPosL P)
{
      return (P->tDato);          
}

tPosL BuscarDato(tLista L,tDato D)
{
    tPosL pos;
    pos=Primera(L);
    while ((pos!=NULO)&&(ObtenerDato(L,pos)!=D)) pos=Siguiente(L,pos);
    return pos;
}

tPosL BuscarDatoOrdenado(tLista L,tDato D)
{
    tPosL pos;
    pos=Primera(L);
    while((pos!=NULO)&&(ObtenerDato(L,pos)<D)) pos=Siguiente(L,pos);
    if(pos==NULO) return NULO;
    else if (ObtenerDato(L,pos)==D) return pos;
    else return NULO;
}

tPosL CrearNodo(tPosL* P,tDato D)
{
    P=malloc(sizeof(*P));
    if(P!=NULO)
    {
        (*P)->dato=D;
        (*P)->sig=NULO;
    }
    return (*P);
}

int InsertarDatoPrimera(tLista* L,tDato D)
{
    tPosL P;
    if (CrearNodo(&P,D)!=NULO)
    {
        return 1;
        if(EsListaVacia(*L)) (*L)=P;
        else
        {
            P->sig=Primera((*L));
            (*L)=P;
        }
    }
    else return 0;
}

int InsertarDatoUltima(tLista* L,tDato D)
{
    tPosL P;
    tPosL Q;
    if(CrearNodo(&P,D)!=NULO)
    {
        if(EsListaVacia(*L))
            (*L)=P;
        else
        {
            Q=Ultima(*L);
            Q->sig=P;
        }
        return 1;
    }
    else return 0;
}

int InsertarDatoPosicion(tLista* L,tDato D,tPosL P)
{
    tPosL Q,R;
    if(CrearNodo(&Q,D)!=NULO)
    {
        if((EsListaVacia(*L))||(P==Primera(*L)))
        {
            Q->sig=(*L);
            (*L)=Q;
        }
        else if(P==NULO)
        {
            R=Ultima(*L);
            R->sig=Q;
        }
        else
        {
            R=Anterior(*L,P);
            R->sig=Q;
            Q->sig=P;
        }
        return 1;
    }
    else return 0;
}

int InsertarDatoOrdenado(tLista* L,tDato D)
{
    tPosL P,Q,R;
    if(CrearNodo(&P,D)!=NULO)
    {

        if((EsListaVacia(*L))||(!EsListaVacia(*L)||ObtenerDato(*L,Primera(*L))>D))
        {
            P->sig=Primera(*L);
            (*L)=P;
        }
        else
        {
            R=Primera(*L);
            Q=Siguiente(*L,R);
            while((Q!=NULO)&&(ObtenerDato(*L,Q)<=D))
            {
                Q=Siguiente(*L,Q);
                R=Siguiente(*L,R);
            }
            if(Q!=NULO)
            {
                (R->sig)=P;
            }
            else
            {
                R=Anterior(*L,Q);
                R->sig=P;
                P->sig=Q;
            }
        }
        return 1;
    }
    else return 0;
}

tDato EliminarPosicion(tLista* L,tPosL P)
{
    tDato D;
    tPosL Q;
    D=ObtenerDato(*L,P);
    if(P==Primera(*L))
    {
        (*L)=Siguiente(*L,P);
        free(P);
    }
    else
    {
        Q=Anterior(*L,P);
        Q->sig=Siguiente(*L,P);
        free(P);
    }
    return D;
}

void EliminarLista(tLista* L)
{
    while(!EsListaVacia(*L)) EliminarPosicion(L,Primera(*L));
}

 
0

w ktorym miejscu?
debugowales?

2

Zaoraj i napisz to od nowa. Więcej się nauczysz niż przepisując na siłę kod z Pascala do C.

0

Czemu odpowiadacie skoro jesteście zbyt leniwi aby przeczytać kod
Gdybym wiedział co jest nie tak to bym go poprawił

4

a placisz mi za to zebym czytal kod?

Czemu jestes taki leniwy? Mogles nauczyc sie programowania i debugowania to sam bys sobie blad znalazl

Zero zaangazowania z Twojej strony i jeszcze pretensje :D

0

Znałem przypadek takiego dzieciaka jak ty
który chociażby mu płacili to i tak nie umiał napisać kodu (wtedy to była trochę bardziej skomplikowana rzecz)
Poza tym po co takie fora jeżeli tylko dzieciaki na nim spamują

4

ok, wytlumacze Ci to jak najprosciej potrafie

Przychodzisz z gotowym kodem (ktory jest dosc duzy) i mowisz "nie dziala, pomozcie" a sam od siebie NIC ale to absolutnie nic nie wykazales (oprocz tego ze przepisales zle z pascala...)

a teraz przyklad z innej dziedziny

Wyobraz sobie, ze masz plan auta i zbudowales auto. Idziesz do warsztatu samochodowego i mowisz "nie dziala, pomozcie". Myslisz ze zrobili by to za darmo?

Za darmo mozesz dostac wskazowki co poprawic. Nikt nie bedzie odwalal czarnej roboty zeby znalezc bledu i jeszcze Ci go poprawic (oczywiscie za darmo)

wiec co jak co to na razie Ty zachowujesz sie jak dziecko.

0

Grzesiek może i bym zaczął pisać od nowa tyle że jeśli nie wiem dlaczego ten segmentation fault wystąpił
to wątpię czy by zadziałało

1

Włącz debuger u klikaj krok po kroku. Nikt tego za ciebie nie zrobi. I nie liczyłbym że ktoś będzie czytał kod po włosku(?).

3

Zastanawiam się jak masz tego segfaulta jak to się nawet nie kompiluje. Przepisz listę od nowa, samemu w stylu c albo c++. Chyba nie bardzo wiesz co ten kod miał robić.

PS.
Sprobowałem to skompilowac na gcc i od razu pokazalo gdzie cos moze nie banglac

tPosL CrearNodo(tPosL* P,tDato D)
{
    P=malloc(sizeof(*P));
    if(P!=NULO)
    {
        (*P)->dato=D;
        (*P)->sig=NULO;
    }
    return (*P);
}

Tutaj alokujesz miejsce na wskaznik (P jest wskaznikiem na wskaznik) nastepnie przypisujesz do tej pamięci dane jakoby to był node. Ale miejsca na dane (noda) nie zaalkowałeś mistrzu.

Jak już to

 tPosL CrearNodo(tPosL *P,tDato D)
{
    *P = (tPosL)malloc(sizeof(**P));
    if(*P!=NULO)
    {
        (*P)->dato=D;
        (*P)->sig=NULO;
    }
    return (*P);
}

I zadziała.

PS2. niedobrze mi jak widzę ten kod.

3
  1. szafujesz returnem w wielu miejscach, np wiesz, że w int InsertarDatoPrimera(tLista* L,tDato D) kod
 if(EsListaVacia(*L)) (*L)=P;
        else
        {
            P->sig=Primera((*L));
            (*L)=P;
        }

nie wykona sie nigdy.

  1. jak nie powiesz, gdzie ci sie wywala, nikt nie będzie bezpłatnie analizował kodu - tu ludzie moga pomóc, ale nie mają czasu na to by analizować Twój kod, bo uważasz, że nie mają nic innego do roboty.
0

Po uruchomieniu debugera pokazuje on na funkcję zwracającą dane w węźle linia 113
Jednak wydaje mi się że nie tam jest błąd
Z Dev C++ się kompiluje ale po uruchomieniu występuje segmentation fault
Gdy bawiłem się łańcuchami to tam segmentation faulta powodował brak alokacji pamięci

0

Mogło się ne skompilować bo zrobiłem literówkę
P->tDato zamiast P->dato

Po zmianie funkcji tworzącej węzeł (na zaproponowaną tutaj alokację nadal jest segmentation fault)

Wasze wpisy potwierdzają że takie fora nie mają sensu

1
Krzywy Lew napisał(a):

Wasze wpisy potwierdzają że takie fora nie mają sensu

I to pisze ktoś kto wkleja na forum hinduski kod po hiszpańsku

0

Znalazłem jeszcze jeden kod w Pascalu i jak go przepisałem to ten błąd nie występuje
Jednak nie ma tam np sprawdzania dostępnej pamięci na węzeł
I kilku funkcji (np usuwanie z głowy , ogona czy całej listy)
Nie ma funkcji do wyszukiwania danych na liście a sortowanie to tylko bąbelki

nalik
Tak na dobrą sprawę pamięć na tablice też tak się alokuje jak to pokazałeś

Lista którą wam przedstawiłem w Pascalu działała i ciekaw jestem czemu tutaj segmentation fault się pojawia

0

Referencja pojawiła się dopiero w C++ i ten drugi wskaźnik ma taką samą rolę co słówko kluczowe var w Pascalu
Poprawna alokacja rozwiązałaby problem ?

Poprawnie napisana lista przydałaby mi się przy zabawie z plikami
Nie musiałbym tyle czytać z dysku , tablica się do tego nie nadaje bo z góry trzeba wiedzieć ile pamięci
trzeba zarezerwować
(W przypadku tablic pamięć rezerwujemy od razu na całą strukturę
W przypadku listy pamięć rezerwujemy przy dodawaniu węzła)

1

Może będzie pomocne ;)


$ valgrind --tool=memcheck --leak-check=full ./a.out 
==20776== Memcheck, a memory error detector
==20776== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==20776== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==20776== Command: ./a.out
==20776== 
==20776== Conditional jump or move depends on uninitialised value(s)
==20776==    at 0x804893D: BuscarDato(tNodo*, int) (prog.cpp:119)
==20776==    by 0x80487BD: main (prog.cpp:58)
==20776== 
==20776== Use of uninitialised value of size 4
==20776==    at 0x804890E: ObtenerDato(tNodo*, tNodo*) (prog.cpp:112)
==20776==    by 0x8048949: BuscarDato(tNodo*, int) (prog.cpp:119)
==20776==    by 0x80487BD: main (prog.cpp:58)
==20776== 
==20776== Use of uninitialised value of size 4
==20776==    at 0x804886B: Siguiente(tNodo*, tNodo*) (prog.cpp:91)
==20776==    by 0x8048932: BuscarDato(tNodo*, int) (prog.cpp:119)
==20776==    by 0x80487BD: main (prog.cpp:58)
==20776== 
Insertando 0
==20776== Use of uninitialised value of size 4
==20776==    at 0x8048A0C: CrearNodo(tNodo**, int) (prog.cpp:138)
==20776==    by 0x8048BA6: InsertarDatoOrdenado(tNodo**, int) (prog.cpp:207)
==20776==    by 0x80487EB: main (prog.cpp:61)
==20776== 
==20776== Invalid write of size 4
==20776==    at 0x8048A0C: CrearNodo(tNodo**, int) (prog.cpp:138)
==20776==    by 0x8048BA6: InsertarDatoOrdenado(tNodo**, int) (prog.cpp:207)
==20776==    by 0x80487EB: main (prog.cpp:61)
==20776==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==20776== 
==20776== 
==20776== Process terminating with default action of signal 11 (SIGSEGV)
==20776==  Access not within mapped region at address 0x0
==20776==    at 0x8048A0C: CrearNodo(tNodo**, int) (prog.cpp:138)
==20776==    by 0x8048BA6: InsertarDatoOrdenado(tNodo**, int) (prog.cpp:207)
==20776==    by 0x80487EB: main (prog.cpp:61)
==20776==  If you believe this happened as a result of a stack
==20776==  overflow in your program's main thread (unlikely but
==20776==  possible), you can try to increase the size of the
==20776==  main thread stack using the --main-stacksize= flag.
==20776==  The main thread stack size used in this run was 8388608.


 

1 użytkowników online, w tym zalogowanych: 0, gości: 1