Elmagyarázná valaki, mi történik ebben a kódban egyáltalán? (C)
Próbálom megérteni, hogyan működnek a C-ben a tömbök, de nem járok sikerrel. Deklarálok egy 10 elemű tömböt, aztán elkezdem feltölteni számokkal. Azt várnám, hogy 9-nél kidobjon egy hibaüzenetet, de ehelyett töltögeti fel tovább, és 2787-nél áll meg.
main()
{
int x[10], y, *p;
for(y=0;1;y++) {x[y]=y+1; printf("%d\n", x[y]);}
}
Nem azt kérem, hogy javítsuk ki a kódot, hanem azt szeretném megérteni, hogy EZ a kód, miért viselkedik úgy, ahogy, miért nem áll meg 10 elemnél, miért különleges a 2787, és mit jelent az, hogy "Szegmentálási hiba (core készült)"
Egyszerű. Az operációs rendszer, amin futtatod, az nem fogja kivédeni a címzésből fakadó hibákat, amíg egy másik program területére nem írsz. Például, ha írsz egy ilyet:
int x[2];
int y;
x[2] = 5;
akkor ez az 5-ös szám az y változódba fog kerülni. Neked azért 2787-nél áll meg, mert a memóriában ott ér véged a te programod, és ott írnál át egy más folyamat memóriaterületére.
Nálam nem ez történik.
*** stack smashing detected ***: ./World terminated
Az y értéke valamiért 1 lesz. :S
Nem tudom, Windows alatt nekem szépen produkálja az általam leírtakat. Nyilván operációs rendszertől függ ez a dolog.
Az utolsó két sor egyáltalán nem lényeg. Windows alatt, ha az a system("pause") nem lenne, akkor még azelőtt bezárna a parancssor, mielőtt még látnék valamit. Az a
return EXIT_SUCCESS;
pedig ugyanaz, mintha azt írnád, hogy:
return 0;
Ugye a main függvényben szereplő return a program futási eredményét jelzi, Windows és a legtöbb egyéb rendszerben ez az érték 0, ha a program sikeresen lefutott, és bármi más egész szám, ha nem. De ez a 0 ettől függetlenül még nem garancia, hogy az adott oprendszeren is így lesz. Ellenben az EXIT_SUCCESS minden rendszeren a sikeres kilépést jelenti (EXIT_FAILURE pedig ha sikertelenül ért véget).
int x[10], y, *p;
for(y=0;1;y++) {x[y]=y+1; printf("%d\n", x[y]);}
Az x-nek lefoglalsz 10 int-nyi helyet a stacken, majd az elejére állítod a pointert. Emiatt ugye x[0] == *x és x[3] == *(x+3).
A túlindexelést nem ellenőrzi alapból semmi. Ugyanúgy a programod által használt memóriaterületre írkálsz. Viszont az általad használható stack végén az oprendszer pofánvágja a programod, hiszen illegális memóriaterületre írkál.
A következő programot először nézd végig, tippeld meg ír-e ki valamit. (á -> a)
(Nem saját szerzemény, Coursera Software Security kurzus mintaprogramja. De gyönyörű.)
Lefoglaltál egy 10 elemű tömböt, majd elkezded kiíratni a tömb elemeit. Az első 10-nél biztos nincs hiba, annyi, hogy memóriaszemetet fogsz kapni, mert nem inicializáltad.
Utána pedig bizonytalan a kód folytatása. Az oprendszer a memóriát felosztja valahogy, van olyan része, amit más program nem írhat, olyan is, amit meg más program nem olvashat, meg olyan is, amit az általad írt program kapja meg veremként + amiket lefoglalsz malloc()-al.
Ha olyan memóriaterületre hivatkozol, amit nem a tiéd (pl x[29]) akkor vagy valami memóraszemetet kapsz vissza vagy pedig hibát. Ez az adott gép adott memóriafelosztásától függ.
A 2787 nem különleges szám, csak a te gépeden éppen a 2787. elemnél léptél ki a stackből, vagy ott talált valami olyan memóriaterületet, ami nem az övé. Az x[n] valójában egy pointer, ami az x[0]-ra mutató pointer + n.
Lényeg: mindig figyelni kell rá, hogy ne hivatkozzunk meg olyan memórarészt, amit nem mi allokáltunk, mert lehet, hogy még Segfault sem lesz, csak memóriaszeméttel dolgozik a program, azt meg nagyon nehéz kijavítani.
"Lefoglaltál egy 10 elemű tömböt, majd elkezded kiíratni a tömb elemeit. Az első 10-nél biztos nincs hiba, annyi, hogy memóriaszemetet fogsz kapni, mert nem inicializáltad."
Inicializáltam, és 1-től írogatja ki a számokat 2787-ig. Csak azt nem értem, hogy miért megy tovább a 10. elemnél, amikor csak 10 van lefoglalva. Minek foglalom le, ha teljesen figyelmen kívül hagyja, és megy tovább? Ha úgy adok meg tömböt, hogy x[3] = {1, 2, 3}, akkor x[3]=4 értékadásnál már kiírja a hibát. Ha meg úgy, ahogy fentebb, akkor simán tovább folytatja 2787-ig.
Az alloc, malloc dolgokat még ugyanezen program megírása közben szeretném megtanulni, de még addig nem jutottam el.
Wampa: a tippem az lett volna, hogy mivel a func() argumentuma 4-nél hosszabb karakterlánc, ezért hiba lesz, és így is lett.
*** stack smashing detected ***: ./World terminated
Félbeszakítva (core készült)
Ugyanakkor ott van az auth változó, ami 0, és utána nem nyúl hozzá sehol, de mégis if-fel ellenőrzi, tehát úgy vélem, annak az értéknek meg kellett volna változnia, ha ez a példa témába vág, akkor a hosszú string felesleges karaktereinek kellett volna megváltoztatnia az auth változó értékét? Nálam nem ez történt.
"*** stack smashing detected ***: ./World terminated
Félbeszakítva (core készült) "
Ezt mi írja ki??
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!