ďťż

Ładny brzuch

Nie wiem czemu np. przy czyms takim wyskakuje segmention fault, core dumped: char *wsk, *wsk='A'
Dokładnie chodzi o to że mam zapisane *char="ala ma kota" i mam to zmienić na duże litery, za pomocą tablic nie mam z tym problemu ale ze wskażnikami nie potrafie bo wyskakują błędy segmention fault




char *wsk, *wsk='A' Zapomniałeś zaalokować pamięć.

oj, ale ja jeszcze nie przerabiałem jakiś funkcji do alokacji pamięci :/

strcpy bedzie Ci potrzebne..
i strlen zdaje sie tez ;)
Użytkownik fernandez edytował ten post 05 styczeń 2008, 23:49


Zależy ile masz tych tekstów do wprowadzenia, ale jesli jeden i ma to być ćwiczenie to proponuję tak:

char napis[]="ala ma kota"; char *wsk=napis; // i tu dzialasz już na wskaźniku

albo tak:
char napis[20]; // tak żeby sie zmieścił napis i jeszcze znak kończący każdy napis char *wsk=napis; scanf("%s",napis);

jeśli więcej to proponuję się zaznajomić z funkcją: char *strdup(char *s) ;)

char* wsk = memalloc( 20 ); // długość stringa *wsk = 'A'; wsk = wsk + 1; *wsk = 'l'; wsk = wsk + 1; *wsk = 0; wsk = wsk - 2; ... free( wsk );
Nie dam głowy czy ta funkcja tak się nazywała (nie kodze w C, tylko C++), lecz tak się mniejwięcej robiło alokacje pamięci i skakało po tablicy. W tym przypadku wsk powinno zawierać adres łańcucha "Al".

//Edit: no tak, ale ja myślałem o czystym C, a tam nie ma operatora inkrementacji i dekrementacji. Chociaż z tego co pamiętam to nowsze wersje już mają ten wynalazek zapożyczony z C++ :P
No i jak na razie nie spotkałem się z platformą sprzętową, gdzie char ma inny rozmiar niż 1 bajt, ale warto sobie wyrabiać takie nawyki jak sizeof. Później łagodniej idzie przejście na wchar_t...
//Edit2: aha - pomyliło mi się :P. Inc i dec był w C, to chyba przeciążanie funkcji doszło z C++ do C :P
Użytkownik Real_Noname edytował ten post 06 styczeń 2008, 16:36
no trochę inaczej to szło:

char *wsk; wsk=malloc(20*sizeof(char)); *wsk++='a'; *wsk++='l'; //i tak dalej free(wsk);

ale tak samo działa własnie funkcja strdup
char *wsk; wsk=strdup("Ala ma kota"); // robisz co musisz free(wsk);

przy strcpy wystarczy tylko:
char *str3; strcpy (str3,"ala ma kota");
bez zwalniania pamieci..

hmm, przecież to nie zadziała...


przy strcpy wystarczy tylko:
char *str3; strcpy (str3,"ala ma kota");
bez zwalniania pamieci..

A teraz pytanie z kapelusza - gdzie i jak to się zapisało, hehe.

Bo łańcuch w cudzysłowie jest lokalny i zostanie usunięty z pamięci po zakończeniu funkcji..., a reszta? :]
//Edit: sorka - łańcuch jest przecież statyczny i zapisane jest na stałe w programie, ale to nie zmienia pierwszego pytania.
Użytkownik Real_Noname edytował ten post 06 styczeń 2008, 13:04

no tak, ale ja myślałem o czystym C, a tam nie ma operatora inkrementacji i dekrementacji. Chociaż z tego co pamiętam to nowsze wersje już mają ten wynalazek zapożyczony z C++ :P
WTF? Od kiedy to w C nie ma ++/--? oO Albo do kiedy nie było?
To niby jak wpadli na nazwę C++? :D.


hmm, przecież to nie zadziała...
moze bys sprawdzil zanim cos takiego napiszesz??


A teraz pytanie z kapelusza - gdzie i jak to się zapisało, hehe.
nie rozumiem..
zapisalo sie w pamieci, wskaznik pokazuje Ci adres :>


nie rozumiem..
zapisalo sie w pamieci, wskaznik pokazuje Ci adres :>

Hehe, i tu jest pies pogrzebany. Wiadomo, że pod jakimś adresem, ale gdzie? Strcpy dostaje wskaźnik na teoretycznie (bo praktycznie to może być z góry ustalony przez kompilator, ale to też nie jest pewne) losowy adres w pamięci. Nie ma żadnych przesłanek, by stwierdzić czy pamięc jest zaalokowana, czy nie, więc na przysłowiową "pałę" kopiuje tam gdzie mu wskazano. A że często ten "losowy" adres wskazuje na blok pamięci zarezerwowany dla programu, to często nie ma problemu. Ale często nie oznacza zawsze - co się stanie, jak wskaźnik będzie na restrykcyjny obszar pamięci? Mamy piękny access violation, z write na czele :].

Czyli suma sumaru - i tak należy przydzielić pamięć, żeby potem nie szukać takich kwiatków.

(jeszcze nie dam głowy, czy strcpy_s specjalnie zabrania takich zastosowań, ale tego nie sprawdzalem)


moze bys sprawdzil zanim cos takiego napiszesz??

ależ ja to sprawdziłem...
naruszenie ochrony pamieci.

dziwne, bo jak bym nie uruchamial programu z:
... char *str; strcpy( str, "ala ma kota" ); printf( "%s\n", str ); ...

to zawsze dziala..

ale coz, pewno masz racje..

sam sie kiedys zasntawialem jak to mozliwe, ale zawsze tak robilem i nigdy bledu nie mialem :>


dziwne, bo jak bym nie uruchamial programu z:
... char *str; strcpy( str, "ala ma kota" ); printf( "%s\n", str ); ...

to zawsze dziala..
ale coz, pewno masz racje..

sam sie kiedys zasntawialem jak to mozliwe, ale zawsze tak robilem i nigdy bledu nie mialem :>

Miałeś farta :). strpcy nie alokuje pamięci. Zakłada że str jest wskaźnikiem na zaalokowaną pamięć. Co więcej strcpy nie sprawdza czy pamięć zostaje przekroczona - informatyk odpowiada zo to żeby drugi parametr nie miał długości przekraczającej długość str (polecane strncpy). Jeżeli to działało to *str = 'a'; też by działało. Co nie znaczy że jest to poprawne, prawda? :)

dzieki za wytlumaczenie :)

a to jest dla mnie już totalne świrowanie tego C

cos takiego wywala błąd:

#include<stdio.h> int main(void) { //char tab[]="kuba ma psa"; char *wsk; *wsk='K'; printf("%c",*wsk); }

a takie cos bezproblemowo dziala:

#include<stdio.h> int main(void) { char tab[]="kuba ma psa"; char *wsk; *wsk='K'; printf("%c",*wsk); }

przecież wskaźnik nie wskazuje na tabele :o

dumny że nauczyłem się malloca przystąpiłem do alokacji tego wskażnika a tu taki błąd strachelny mi wyskoczył :/
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0804a00a *** ======= Backtrace: ========= /lib/tls/i686/cmov/libc.so.6[0xb7ee6d65] /lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7eea800] ./a.out[0x80483e3] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7e93050] ./a.out[0x8048341] ======= Memory map: ======== 08048000-08049000 r-xp 00000000 08:01 17007687 /home/kuba/a.out 08049000-0804a000 rw-p 00000000 08:01 17007687 /home/kuba/a.out 0804a000-0806b000 rw-p 0804a000 00:00 0 [heap] b7d00000-b7d21000 rw-p b7d00000 00:00 0 b7d21000-b7e00000 ---p b7d21000 00:00 0 b7e71000-b7e7b000 r-xp 00000000 08:01 4505667 /lib/libgcc_s.so.1 b7e7b000-b7e7c000 rw-p 0000a000 08:01 4505667 /lib/libgcc_s.so.1 b7e7c000-b7e7d000 rw-p b7e7c000 00:00 0 b7e7d000-b7fc1000 r-xp 00000000 08:01 4539714 /lib/tls/i686/cmov/libc-2.6.1.so b7fc1000-b7fc2000 r--p 00143000 08:01 4539714 /lib/tls/i686/cmov/libc-2.6.1.so b7fc2000-b7fc4000 rw-p 00144000 08:01 4539714 /lib/tls/i686/cmov/libc-2.6.1.so b7fc4000-b7fc7000 rw-p b7fc4000 00:00 0 b7fd6000-b7fd8000 rw-p b7fd6000 00:00 0 b7fd8000-b7ff2000 r-xp 00000000 08:01 4506203 /lib/ld-2.6.1.so b7ff2000-b7ff4000 rw-p 00019000 08:01 4506203 /lib/ld-2.6.1.so bfe98000-bfead000 rw-p bfe98000 00:00 0 [stack] ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso] Aborted (core dumped)

moje - OS: ubuntu, kompilator: gcc

u Was też taki błąd po wstukaniu tego kodu
char *wsk; wsk=malloc(20*sizeof(char)); *wsk++='a'; *wsk++='l'; //i tak dalej free(wsk);
Użytkownik kuba bobas edytował ten post 07 styczeń 2008, 14:21

a to jest dla mnie już totalne świrowanie tego C

cos takiego wywala błąd:
...
przecież wskaźnik nie wskazuje na tabele :o

Ale wskazuje na te same miejsce w stosie. Dlatego mówiłem, że "teoretycznie" jest losowe miejsce wskaźnika. To wszystko zależy od kompilatora/ustawień, itp.


u Was też taki błąd po wstukaniu tego kodu
char *wsk; wsk=malloc(20*sizeof(char)); *wsk++='a'; *wsk++='l'; //i tak dalej free(wsk);

Zgaduje, że w dalszej części kodu nie wracasz na miejsce wskaźnikiem i podajesz funkcji free zle miejsce w pamięci.


Ale wskazuje na te same miejsce w stosie. Dlatego mówiłem, że "teoretycznie" jest losowe miejsce wskaźnika. To wszystko zależy od kompilatora/ustawień, itp. O qrcze, a przeważnie tak jest że jak najpierw zadeklaruje tablice to poniej kazdy zadeklarowany wskaznik przyjmuje domyslnie adres poczatku tej tablicy?


Zgaduje, że w dalszej części kodu nie wracasz na miejsce wskaźnikiem i podajesz funkcji free zle miejsce w pamięci.
zgadza się.

Czy jedynym sposobem na cofnięcie wskaznika do poczatku jest tyle razy deinkrementować co sie inkrementowało? próbowałem cos takiego, ale nie skompilowało :/

#include<stdio.h> #include<stdlib.h> int main(void) { char *wsk=malloc(20*sizeof(char)); int x; x=wsk; *wsk++='a'; *wsk++='l'; *wsk++='a'; wsk=x; free(wsk); printf(wsk); }

napewno nie:
int x;
ale
char *x;

a to co jest??
printf(wsk);to nie Pascal :P


a to co jest??
printf(wsk);to nie Pascal :P

Oczywiście, że nie. To C :]

Tyle że tu jest duże prawdopodobieństwo na Access Violation i dodatkowo aż prosi się o atak hackerski :]. Nigdy, ale to NIGDY nie dawajcie stringu na format w printf. Prawidłowo jest:

printf( "%s", wsk )
Bezpieczny, i nie da się nic przekabacić :)

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •