[Rozw]Ciekawy przypadek "Segmentation fault", C.

Problemy dotyczące programowania.

Moderatorzy: Moderatorzy, Administratorzy

Pajaczek
Użytkownik
Posty: 1439
Rejestracja: 2006-08-03, 13:16
Lokalizacja: Winny Gród

[Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: Pajaczek »

Witam.

taki fragment main:

Kod: Zaznacz cały

struct timeval w1, w2; 
for (;;) {
  if (SDL_PollEvent(&event)) {
    if (event.type == SDL_QUIT || event.type == SDL_KEYDOWN) {
      return 0;
    }
  }
  if (!(tick % 20)) {
    funkcja(d1, d2, time(), 5);
  }
  tick++;
  SDL_Delay(50);
}
oraz wygląd funkcji

Kod: Zaznacz cały

int funkcja(struktura a, struktura b, Uint32 c, Uint8 d) {
  return 1;
}
W takiej postaci powoduje segmentation fault, ale uwaga: wystarczy wykonać jedno z 3 działań (dowolne):
1) usunąć wywołanie funkcji (co jest w sumie dziwne bo ona jak widać jedynie zwraca 1)
2) usunąć warunek "if (!(tick % 20))" oczywiście z odpowiednimi klamrami (czyli inaczej mówiąc funkcja jest wywoływana 20 razy częściej),
3) usunąć z kodu zmienną w2

i błąd segmentacji znika... ma ktoś jakąś ideę co może tu zawinić??

Dam sobie radę inaczej w kodzie - zresztą w1 i w2 miały mi tylko pomóc przetestować czas wykonania pewnego fragmentu kodu, więc w ostatecznej wersji są zbyteczne - ale ciekaw jestem co może być przyczyną takiego zachowania. Problem powstał właśnie gdy dodałem w2. Jeśli ktoś podejrzewa, że przyczyna może leżeć w innym fragmencie kodu to ew. zamieszczę.
Ostatnio zmieniony 2009-03-07, 22:07 przez Pajaczek, łącznie zmieniany 2 razy.
acek
Użytkownik
Posty: 47
Rejestracja: 2006-09-26, 21:27
Kontakt:

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: acek »

Funkcja time(2) przyjmuje argument. Pamietałeś o dołączeniu time.h? Dobrze jest mieć włączoną opcję -Wall programu cc(1).
Ostatnio zmieniony 2009-03-07, 01:52 przez acek, łącznie zmieniany 1 raz.
Pajaczek
Użytkownik
Posty: 1439
Rejestracja: 2006-08-03, 13:16
Lokalizacja: Winny Gród

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: Pajaczek »

acek, program się kompiluje, a więc nie ma mowy o niedołączonych nagłówkach ;)
Odnośnie time()... za man 2 time, jeśli argument nie jest NULLem to należy podać wskaźnik na time_t, ale argument może być NULL.

Btw. podejrzewam, że to może być problem ze sprzętem. Dodanie lub usunięcie niewykorzystanych zmiennych też potrafi spowodować seg fault, albo ekstrawagancja, ze zmienną "char zm[70]" jest segfault, ale jak zmienie na "char zm[80]" LUB "char zm[4]" to jest ok :devil:
Ale też dziwne by to był problem sprzętowy, bo jedynie moje programy powodują segfaulty - jak narazie.
Awatar użytkownika
mina86
Moderator
Posty: 3343
Rejestracja: 2004-06-14, 21:58
Lokalizacja: Linux 5.x x86_64
Kontakt:

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: mina86 »

Pajaczek pisze:acek, program się kompiluje, a więc nie ma mowy o niedołączonych nagłówkach ;)
Widać, że sporo jeszcze nie wiesz o języku C:

Kod: Zaznacz cały

[mina86@erwin ~/code]$ cat foo.c 
int main(void) { puts("hello, world"); return 0; }
[mina86@erwin ~/code]$ gcc -o foo foo.c
[mina86@erwin ~/code]$ ./foo 
hello, world
Skorzystaj z rady acka i skompiluj z opcją -Wall i ode mnie dodaj jeszcze -Werror:

Kod: Zaznacz cały

[mina86@erwin ~/code]$ cat foo.c 
int main(void) { puts("hello, world"); return 0; }
[mina86@erwin ~/code]$ gcc -Wall -Werror -o foo foo.c
cc1: warnings being treated as errors
foo.c: In function 'main':
foo.c:1: warning: implicit declaration of function 'puts'
Zastrzegam sobie prawo nieanalizowania postów pisanych niepoprawną polszczyzną.
Post generated automatically by A.I. system code name ‘mina86’ in response to the previous one.
Pajaczek
Użytkownik
Posty: 1439
Rejestracja: 2006-08-03, 13:16
Lokalizacja: Winny Gród

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: Pajaczek »

mina86 pisze:Widać, że sporo jeszcze nie wiesz o języku C:
No z tym się bezapelacyjnie zgodzę... powiem więcej, nigdy nie będę wiedział dostatecznie dużo (by się nasycić ;-)).
Jednak to co pokazałeś dowodzi jedynie, że niedołączone nagłówki mogą być włączone przez kompilator (o ile sobie z tym da radę), nie wyjaśnia to jednak sytuacji z mojego pytania (przypominam, jedna zmienna timeval nie sprawiała problemu, problem był przy deklaracji 2-giej).

No więc tak, nagłówek time miałem włączony, wersję <sys/time.h>. Wcześniej coś mi właśnie zgłosiło brak deklaracji akurat nagłówka time więc włączyłem. Zresztą mam nawyk, może błędny, pilnowania includów i sprawdzania ich przy pierwszych błędach.
W takiej kombinacji (sys/time.h) funkcja time może być wywołana (i działa) bez argumentów, w przypadku <time.h> musiałbym podać argument -> time(0). Może dla porządku zostawię na razie <time.h>. Edit akapitu: no i wiem dlaczego akurat <sys/time.h>.. ze względu na gettimeofday ;-)

Segfaulty pojawiły mi się jeszcze jak USUNĄŁEM pewne zbędne deklaracje zmiennych (np. deklaracje 2 nieużytych w programie int). Czego już zupełnie nie rozumiem, mogę się jedynie domyślać, choć w świetle tego co ostatnio, chyba nawet Ty mina86 napisałeś o optymalizacji, to moje domysły były by błędne.

Po usunięciu wszystkich zbędnych deklaracji zmiennych z main, program przestał wyrzucać segfaulty, w pełnej wersji, tzn. z listingu w poście 1 (z tą różnicą ze funkcja odzyskała swoją pełną treść, a nie tylko return 1).

Teraz co po -Wall -Werror:
otrzymuje jedynie zaginione deklaracje time, gettimeofday, brak return int w funkcji która powinna go mieć, 2 razy zakomentowany znacznik początku komentarza (/*) i jedna nieużytą zmienną. Czyli same głupotki. Spróbuję przywrócić (z ciekawości) postać w której otrzymywałem segfaulty i zobaczyć co wówczas wykrzyczy.
Ostatnio zmieniony 2009-03-07, 15:43 przez Pajaczek, łącznie zmieniany 3 razy.
kazek3018
Użytkownik
Posty: 181
Rejestracja: 2006-12-10, 14:27

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: kazek3018 »

Coś mi się zdaje, że błąd jest gdzieś indziej. Sprawdź program w miejscach, gdzie używasz wskaźnika do poruszania się po jakimś ciągłym obszarze pamięci. Nie zaszkodzi zamienić time() na time(NULL).

Zmiany które opisujesz powodują reorganizacje pliku wykonywalnego, więc raz wejdziesz gdzieś na jakieś dane a raz nie.

Odnośnie SDL-a, to posprawdzaj czy do funkcji które tego oczekują przesyłasz zawsze wskaźnik do ciągłego obszaru pamięci. Kolega miał kiedyś problemy z OpenGL bo obraz wczytywał do tablicy Tab[800][600] zamiast do Tab[800*600].
acek
Użytkownik
Posty: 47
Rejestracja: 2006-09-26, 21:27
Kontakt:

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: acek »

Pajaczek pisze:acek, program się kompiluje, a więc nie ma mowy o niedołączonych nagłówkach ;)
Odnośnie time()... za man 2 time, jeśli argument nie jest NULLem to należy podać wskaźnik na time_t, ale argument może być NULL.
W języku C

Kod: Zaznacz cały

time(NULL);
nie jest równoważne z

Kod: Zaznacz cały

time();
W języku C nie ma domyślnych wartości argumentów.
Pajaczek pisze:Btw. podejrzewam, że to może być problem ze sprzętem. Dodanie lub usunięcie niewykorzystanych zmiennych też potrafi spowodować seg fault, albo ekstrawagancja, ze zmienną "char zm[70]" jest segfault, ale jak zmienie na "char zm[80]" LUB "char zm[4]" to jest ok :devil:
Ale też dziwne by to był problem sprzętowy, bo jedynie moje programy powodują segfaulty - jak narazie.
To są typowe objawy dla Twojego problemu. Nie przekazujesz wymaganego argumentu. Kompilator nie zna prototypu wołanej funkcji, więc nie zgłasza błędu. Funkcja zamiast argumentu otrzymuje to, co zostało pozostawione w pamięci, gdzie powinna być wartość argumentu. To, co się tam znajdzie zależy m.in. od rozmiaru obiektów lokalnych.

To nie jest problem sprzętowy.

Proponuję lekturę http://www.linuxtraining.com/developers ... i386-4.pdf, (rozdział "Function Calling Sequence") lub dokumentu odpowiedniego dla Twojej architektury.
Pajaczek pisze:otrzymuje jedynie zaginione deklaracje time, gettimeofday, brak return int w funkcji która powinna go mieć, 2 razy zakomentowany znacznik początku komentarza (/*) i jedna nieużytą zmienną. Czyli same głupotki.
Ostrzeżenia, o których piszesz, nie należą do tych, które należy lekceważyć (z wyjątkiem niewykorzystanej zmiennej i może podwójnego komentarza). To nie są "głupotki". Nie bez powodu dobre programy są kompilowane z opcjami -Wall i -Werror.

Poza tym, możesz skorzystać z debuggera, by sprawdzić, jaki argument otrzymuje time(2).

Pobaw się tym (celowo niepoprawnym) programikiem:

Kod: Zaznacz cały


#include <stdio.h>

void foo(a,b)
{
        printf("a = %i, b = %i\n",a,b);
}

main()
{
        void (*fp)();

        fp = foo;
        fp(1,2,3);
        fp(4,5);
        fp(6);
        fp();
        return 0;
}
Ostatnio zmieniony 2009-03-13, 21:30 przez acek, łącznie zmieniany 2 razy.
Awatar użytkownika
mina86
Moderator
Posty: 3343
Rejestracja: 2004-06-14, 21:58
Lokalizacja: Linux 5.x x86_64
Kontakt:

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: mina86 »

Pajaczek pisze:No więc tak, nagłówek time miałem włączony, wersję <sys/time.h>.

Kod: Zaznacz cały

[mina86@erwin ~/code]$ cat foo.c
#include <sys/time.h>
int main(void) { return time(); }
[mina86@erwin ~/code]$ gcc -Wall foo.c
foo.c: In function 'main':
foo.c:2: warning: implicit declaration of function 'time'
Bądź zgodny z językiem i dołącz to time.h, a funkcje wywołuj jako time(0).
Pajaczek pisze:Teraz co po -Wall -Werror:
otrzymuje jedynie zaginione deklaracje time, gettimeofday, brak return int w funkcji która powinna go mieć, 2 razy zakomentowany znacznik początku komentarza (/*) i jedna nieużytą zmienną. Czyli same głupotki.
Wygląda na to, że potrzebujesz więcej doświadczenia w pisaniu w C zanim będziesz mógł oceniać co jest głupotą, a co nie. Brak deklaracji time() i wywoływanie tej funkcji bez argumentu może mieć katastrofalne skutki.
Zastrzegam sobie prawo nieanalizowania postów pisanych niepoprawną polszczyzną.
Post generated automatically by A.I. system code name ‘mina86’ in response to the previous one.
Pajaczek
Użytkownik
Posty: 1439
Rejestracja: 2006-08-03, 13:16
Lokalizacja: Winny Gród

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: Pajaczek »

acek pisze:To są typowe objawy dla Twojego problemu. Nie przekazujesz wymaganego argumentu. Kompilator nie zna prototypu wołanej funkcji, więc nie zgłasza błędu. Funkcja zamiast argumentu otrzymuje to, co zostało pozostawione w pamięci, gdzie powinna być wartość argumentu. To, co się tam znajdzie zależy m.in. od rozmiaru obiektów lokalnych.
Tak... to mnie przekonuje, że tu popełniłem błąd. Trochę może zbyt beztrosko się poczułem gdyż bardzo późno się ten błąd objawił.
acek pisze:W języku C nie ma domyślnych wartości argumentów.
Tak... wiem o tym... choć czasem się lekceważy... jak widać prędzej czy później się to przypomina. Debuggerem pobawię się jak będzie chwila luźniejsza, i nie na tym sprzęcie, bo bez GUI to trzeba się przestawić.
kazek3018 pisze:Zmiany które opisujesz powodują reorganizacje pliku wykonywalnego, więc raz wejdziesz gdzieś na jakieś dane a raz nie.
Niby tak, z wyjątkiem usunięcia niewykorzystanych zmiennych, jak pokazał niedawno mina86 w innym temacie gcc i tak je ignorował (usuwał).

[ Dodano: 2009-03-07, 22:13 ]
kazek3018 pisze:Odnośnie SDL-a, to posprawdzaj czy do funkcji które tego oczekują przesyłasz zawsze wskaźnik do ciągłego obszaru pamięci. Kolega miał kiedyś problemy z OpenGL bo obraz wczytywał do tablicy Tab[800][600] zamiast do Tab[800*600].
SDL akurat umożliwia tworzenie powierzchni, sam rezerwuje odpowiednie miejsce.
Ostatnio zmieniony 2009-03-07, 22:14 przez Pajaczek, łącznie zmieniany 1 raz.
Awatar użytkownika
mina86
Moderator
Posty: 3343
Rejestracja: 2004-06-14, 21:58
Lokalizacja: Linux 5.x x86_64
Kontakt:

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: mina86 »

Pajaczek pisze:Niby tak, z wyjątkiem usunięcia niewykorzystanych zmiennych, jak pokazał niedawno mina86 w innym temacie gcc i tak je ignorował (usuwał).
Że niby co pokazywałem?
Zastrzegam sobie prawo nieanalizowania postów pisanych niepoprawną polszczyzną.
Post generated automatically by A.I. system code name ‘mina86’ in response to the previous one.
Pajaczek
Użytkownik
Posty: 1439
Rejestracja: 2006-08-03, 13:16
Lokalizacja: Winny Gród

Re: [Rozw]Ciekawy przypadek "Segmentation fault", C.

Post autor: Pajaczek »

Coś mi się kołatało w głowie że podałeś przykład, a to było tylko suche stwierdzenie: TU

A tak jeszcze porządkowo... acek mógłbyś poprawić zamieszczonego linka?? A ten tekst zapowiada się ciekawie... na pewno przyjrzę mu się.
ODPOWIEDZ