| | |
| Stránka: 1 z 1
| [ Príspevkov: 12 ] | |
Autor | Správa |
---|
Registrovaný: 17.08.12 Prihlásený: 02.01.15 Príspevky: 94 Témy: 29 | Napísal JTB: 27.10.2013 11:16 | |
|
Naprogramoval som rekurzívnu dátovú štruktúru lineárny spájaný zoznam bez nárazníka v jazyku C, funguje ako má, len som náhodou zistil, že predsa pri určitách zmenách v programe padne. Definícia štrukúr:Kód: typedef struct{ char meno[10]; char priezvisko[20]; int hodnota; }ZAZNAM;
typedef struct atom{ ZAZNAM *p_zaznam; struct atom *p_dalsi; }ATOM;
typedef struct{ ATOM *p_zac, *p_index, *p_kon; }ZOZNAM; Nebudem tu písať celý program, je vcelku obsiahlejší, ale napíšem len problematické časti. Príčina chyby bude určite v nich. 1. chyba.Definujem si premennú ZOZNAM *p_zoznam; Pracujem s ňou, všetko funguje ako má. Ale ako náhle som si definoval premennú ZAZNAM zaz; program začal padaj. Konkrétne padá pri inicializácii *p_zoznam. Inicializácia vyzerá takto:Kód: void ini(ZOZNAM **p_zoznam) { (*p_zoznam)->p_zac = (*p_zoznam)->p_index = (*p_zoznam)->p_kon = NULL; } Volám ju:Kód: ini(&p_zoznam); Ako náhme namiesto ZAZNAM zaz, dekrarujem a definujem pointer na ZAZNAM a alokujem pre neho pamäť, Kód: ZAZNAM *p_zaz = (ZAZNAM*)malloc(siezeof(ZAZNAM); všetko funguje ako má, len samozrejme musím pracovať s premennou p_zaz ako s pointerom. Prečo je tomu tak?2. chybaVždy pri alokácii pamäte testujem či je dosť pamäte: Kód: if(((*p_zoznam)->p_zac = (ATOM*)malloc(sizeof(ATOM))) == NULL) { printf("Malo pamate"); exit(1); }
Avšak som nechtiec urobil chybu if(((*p_zoznam)->p_zac = (ATOM*)malloc(sizeof(ATOM))) != NULL) - namiesto == som použil != a program spadol i keď sa mal len ukončiť. Vypísalo sa "Malo pamate" a namiesto ukončenia programu, program spadol. Deje sa to len v tomto bloku kódu:Mám makrá : #define atm (ATOM*)malloc(sizeof(ATOM)) #define zaz (ZAZNAM*)malloc(sizeof(ZAZNAM)) #define test_pamate {printf("Malo pamate"); exit(1);} Kód: void pridaj(ZOZNAM **p_zoznam, ZAZNAM *zaznam) { if(test(*p_zoznam)) {
if(((*p_zoznam)->p_zac = atm) == NULL) test_pamate;
if(((*p_zoznam)->p_zac->p_zaznam = zaz) == NULL) test_pamate;
(*p_zoznam)->p_zac->p_zaznam->hodnota = zaznam->hodnota; strcpy((*p_zoznam)->p_zac->p_zaznam->meno, zaznam->meno); strcpy((*p_zoznam)->p_zac->p_zaznam->priezvisko, zaznam->priezvisko);
(*p_zoznam)->p_zac->p_dalsi = NULL; (*p_zoznam)->p_kon = (*p_zoznam)->p_index = (*p_zoznam)->p_zac; } else if(test_kon(*p_zoznam)) {... Funkciu pridaj volám bezprostredne po inicializácii a tento blok kódu vytvára prvý atóm v zozname, nech kdekoľvek do tohoto bloku pridám exit(1); program spadne. Taktiež som zistil že ak inicializujem zoznam a nič do neho nepridám len hneď zavolám funkciu exit, program namiesto ukončenia spadne. Takže táto chyba sa zrejme sťahuje len na inicializovaný zoznam v ktorom nie sú žiadné atómy. Vedeli by ste mi povedať prečo?
_________________ HP ProBook 4520s; CPU: Intel i5-480M 2,67 Ghz; GPU: ATI Radeon HD 6370M 1 GB; MB: Hewlett-Packard 1411; Chipset: IntelHM57 (IbexPeak-M DH); RAM: Hyundai DDR3 4GB (PC3-10600); HDD: Hitachi 500GB 7200RPM SATA-II; Zvuková karta: Axago ADA-X5; Reproduktory: Genius SW-G2.1 1250 GX Gaming; OS: openSUSE 13.1, 64-bit |
|
Registrovaný: 13.11.07 Prihlásený: 20.08.16 Príspevky: 1702 Témy: 0 | Napísal chrono: 27.10.2013 13:53 | |
|
Premenná definovaná pomocou ZOZNAM *p_zoznam; odkazuje na nejaké náhodné miesto v pamäti (alebo na adresu 0, ak ide o globálnu premennú), takže nie je prekvapujúce, že pri pokuse o prístup k takejto premennej program spadne.
|
|
Registrovaný: 17.08.12 Prihlásený: 02.01.15 Príspevky: 94 Témy: 29 | Napísal autor témy JTB: 27.10.2013 14:06 | |
|
Neviem presne čo myslíš... Premennú ZOZNAM *p_zoznam; najskôr pred použitím inicializujem, teda aby ukazovala na NULL resp. ukazuje nikam. Ak do nej vkladám hodnoty, tak pre ňu alokujem miesto a až potom vkladám hodnoty. Všetko funguje ako má. Jedine nastane chyba ak len inicializujem premennú ini(&p_zoznam); a hneď následne použijem funkciu exit();. Vtedy program spadne. Do premennej p_zoznam predsa nepristupujem, len zavolám funkciu exit(); ktorá ukočí beh programu tj. funckiu main. Veď predsa Kód: if(((*p_zoznam)->p_zac = (ATOM*)malloc(sizeof(ATOM))) == NULL) { printf("Malo pamate"); exit(1); } je celkom bežná testovacia podmienka. Ak sa nepodarí alokovať miesto pre premennu funckia vráti NULL a program sa ukončí. Vtedy tiež daná premenná neukazuje nikam alebo na náhodné miesto v pamäti a program nespadne len sa ukončí.
_________________ HP ProBook 4520s; CPU: Intel i5-480M 2,67 Ghz; GPU: ATI Radeon HD 6370M 1 GB; MB: Hewlett-Packard 1411; Chipset: IntelHM57 (IbexPeak-M DH); RAM: Hyundai DDR3 4GB (PC3-10600); HDD: Hitachi 500GB 7200RPM SATA-II; Zvuková karta: Axago ADA-X5; Reproduktory: Genius SW-G2.1 1250 GX Gaming; OS: openSUSE 13.1, 64-bit |
|
Registrovaný: 13.11.07 Prihlásený: 20.08.16 Príspevky: 1702 Témy: 0 | Napísal chrono: 27.10.2013 17:03 | |
|
Kód: (*p_zoznam)->p_zac = (*p_zoznam)->p_index = (*p_zoznam)->p_kon = NULL; kód pristupuje k tej premennej tri krát a ak p_zoznam neobsahovala adresu nejakým spôsobom vyhradenú pre ten objekt, tak prepisuje dáta na náhodnej adrese.
|
|
Registrovaný: 17.08.12 Prihlásený: 02.01.15 Príspevky: 94 Témy: 29 | Napísal autor témy JTB: 27.10.2013 18:17 | |
|
A vedel by si mi to aj bližšie vysvetliť prečo program spadne ak zavolám funckiu exit()? Ak sa pokúšam napr. p_zoznam->p_kon->p_zaznam->hodnota = 8; a nealokoval sa pre p_zoznam a pre p_zaznam miesto v pamäti mi je jasné, že program spadne. Ale ak by si vedel potreboval/chcel by som aj nejaké konkrétnejšie vysvetlenie prečo to padá pri použití exit(); A vedel by si mi poradiť aj s druhou časťou problému prečo nemôžem deklarovať premennú ZAZNAM zazn;?ALe musím na ňu použiť pointer ZAZNAM *p_zaz?
_________________ HP ProBook 4520s; CPU: Intel i5-480M 2,67 Ghz; GPU: ATI Radeon HD 6370M 1 GB; MB: Hewlett-Packard 1411; Chipset: IntelHM57 (IbexPeak-M DH); RAM: Hyundai DDR3 4GB (PC3-10600); HDD: Hitachi 500GB 7200RPM SATA-II; Zvuková karta: Axago ADA-X5; Reproduktory: Genius SW-G2.1 1250 GX Gaming; OS: openSUSE 13.1, 64-bit |
|
Registrovaný: 13.11.07 Prihlásený: 20.08.16 Príspevky: 1702 Témy: 0 | Napísal chrono: 27.10.2013 19:44 | |
|
Pretože, ak je napr. tá premenná v zásobníku (napr. preto, že nie je globálna), tak je dosť možné, že jej obsah bude (len náhodou) odkazovať na skutočnú adresu (pretože takmer každá funkcia, bude svoje údaje ukladať práve do zásobníka) a tak sa môže stať, že sa prepíšu nejaké potrebné údaje.
Taká premenná sa definovať dá.
|
|
Registrovaný: 17.08.12 Prihlásený: 02.01.15 Príspevky: 94 Témy: 29 | Napísal autor témy JTB: 27.10.2013 20:10 | |
|
A ako by sa to dalo napraviť aby program nespadol? A tiež som si myslel, že sa to dá, teda aj si myslím stále že sa to dá, ale nevedno prečo program mi vždy spadne ak definujem len ZAZNAM zazn; Nemusím s touto premennou ani pracovať, len ju definujem a program padá. Zistil som len, že program padne ak dôjde k riadku s inicializáciou ZOZNAM *p_zoznam, teda k riadku s ini(&p_zoznam); a ešte som zistil, že ak zo štruktúry ZAZNAM odstrániť stringy a nechám tam len int, tak môžem definovať ZAZNAM zazn; aby program nespadol. Akonáhle tam pridám aj string, program padne.
_________________ HP ProBook 4520s; CPU: Intel i5-480M 2,67 Ghz; GPU: ATI Radeon HD 6370M 1 GB; MB: Hewlett-Packard 1411; Chipset: IntelHM57 (IbexPeak-M DH); RAM: Hyundai DDR3 4GB (PC3-10600); HDD: Hitachi 500GB 7200RPM SATA-II; Zvuková karta: Axago ADA-X5; Reproduktory: Genius SW-G2.1 1250 GX Gaming; OS: openSUSE 13.1, 64-bit |
|
Registrovaný: 13.11.07 Prihlásený: 20.08.16 Príspevky: 1702 Témy: 0 | Napísal chrono: 27.10.2013 20:59 | |
|
Ak v ATOM naozaj musí byť ukazovateľ na ZAZNAM, tak sa musí ten ZAZNAM nejakým spôsobom alokovať a odkaz sa uloží do tej premennej p_zaznam.
Samotná premenná zoznam môže byť priamo typu ZOZNAM a tie prvky sa inicializujú na NULL.
|
|
Registrovaný: 17.08.12 Prihlásený: 02.01.15 Príspevky: 94 Témy: 29 | Napísal autor témy JTB: 27.10.2013 21:57 | |
|
Pointer na ZAZNAM tam predsa musí byť, inak by tá rekurzia nemala zmysel, keďže by jednotlivé prvky neniesli žiadnu hodnotu, len ukazovali na seba. A viem, že musím alokovať pamäť pre ZAZNAM a viem že sa uloží odkaz na začiatok bloku alokovanej pamäte do premennej p_zaznam, veď presne tak to mám v programe ak do lineárneho zoznamu vkladám prvky, len nejako neviem čo tým chceš povedať vzhladom na moju otázku...A ešte ma zaujímalo prečo sa nedá definovať priamo premenná ZAZNAM zazn; a nie prostredníctvom ZOZNAM-u...
_________________ HP ProBook 4520s; CPU: Intel i5-480M 2,67 Ghz; GPU: ATI Radeon HD 6370M 1 GB; MB: Hewlett-Packard 1411; Chipset: IntelHM57 (IbexPeak-M DH); RAM: Hyundai DDR3 4GB (PC3-10600); HDD: Hitachi 500GB 7200RPM SATA-II; Zvuková karta: Axago ADA-X5; Reproduktory: Genius SW-G2.1 1250 GX Gaming; OS: openSUSE 13.1, 64-bit |
|
Registrovaný: 13.11.07 Prihlásený: 20.08.16 Príspevky: 1702 Témy: 0 | Napísal chrono: 27.10.2013 22:29 | |
|
Myslel som to tak, že ATOM môže vyzerať aj takto: Kód: typedef struct atom{ ZAZNAM zaznam; struct atom *p_dalsi; }ATOM; (v niektorých prípadoch ale môže byť výhodnejšie mať to ako odkaz) Premenná ZAZNAM zazn; sa bez problémov definovať dá. Samozrejme ak sa definuje v zásobníku, tak je prístupná len v tej funkcii, v ktorej bola definovaná a po opustení tej funkcie tie údaje môžu byť prepísané.
|
|
Registrovaný: 17.08.12 Prihlásený: 02.01.15 Príspevky: 94 Témy: 29 | Napísal autor témy JTB: 27.10.2013 23:02 | |
|
V programe to mám momentálne riešené takto Kód: int main() { ZOZNAM *p_zoznam; ZAZNAM *p_min; FILE *fw, *fr; int dlzka, i, j = 1, k;
ini(&p_zoznam); ...
Samozjreme platí všetko čo som písal vyšsie. Toto funguje bez problémov, všetky procedúry a funkcie mám odskúšané niekoľko krát a program nespadol ani sa nesprával nevypočítateľne. Lenže ZAZNAM *p_min; vôbec nepotrebujem aby bol dynamický. Slúži len na dočasné "uskladnenie minima" na čo by mi stačila i statická premenná. Samozrejme ani keď je to takto, mi to nerobí problém a ani to neovplivňuje program len skôr ide o teoretickú otázku a ušetrení riadku kódu pre alokovanie miesta pre ňu. Keď však spravím toto (Zmením ukazovateľ na typ ZAZNAM *p_min na statickú premennú ZAZNAM min;) Kód: int main() { ZOZNAM *p_zoznam; ZAZNAM min; FILE *fw, *fr; int dlzka, i, j = 1, k;
ini(&p_zoznam); ...
program spadne ihneď pri inicializácii p_zoznam.
_________________ HP ProBook 4520s; CPU: Intel i5-480M 2,67 Ghz; GPU: ATI Radeon HD 6370M 1 GB; MB: Hewlett-Packard 1411; Chipset: IntelHM57 (IbexPeak-M DH); RAM: Hyundai DDR3 4GB (PC3-10600); HDD: Hitachi 500GB 7200RPM SATA-II; Zvuková karta: Axago ADA-X5; Reproduktory: Genius SW-G2.1 1250 GX Gaming; OS: openSUSE 13.1, 64-bit |
|
Registrovaný: 13.11.07 Prihlásený: 20.08.16 Príspevky: 1702 Témy: 0 | Napísal chrono: 28.10.2013 16:36 | |
|
Pretože tam prepisuješ dáta na náhodnej adrese. Buď tam daj Kód: ZOZNAM zoznam; , alebo alokuj pamäť pre tú štruktúru ZOZNAM a adresu ulož do p_zoznam.
|
|
| Stránka: 1 z 1
| [ Príspevkov: 12 ] | |
Podobné témy | Témy | Odpovede | Zobrazenia | Posledný príspevok |
---|
| Spajany zoznam , C# v Technológia .NET | 2 | 1440 | 06.12.2010 18:10 walther | | Spajany zoznam C v Assembler, C, C++, Pascal, Java | 2 | 1937 | 28.04.2015 22:24 JanoF | | C - spajany zoznam struktur - help v Assembler, C, C++, Pascal, Java | 2 | 393 | 02.05.2014 19:29 TieSTiK | | Jednosmerny spajany zoznam struktur v C v Assembler, C, C++, Pascal, Java | 7 | 1778 | 08.05.2013 15:28 BX | | Zoznam v JavaScript, VBScript, Ajax | 1 | 1863 | 25.06.2012 0:08 shaggy | | zoznam v HTML, XHTML, XML, CSS | 10 | 2274 | 05.08.2007 10:20 HAE07 | | zoznam v HTML, XHTML, XML, CSS | 17 | 2946 | 23.06.2007 22:06 sento | | zoznam moderatorov v Redakčné systémy | 10 | 912 | 23.08.2006 19:38 gumy | | zoznam kontaktov v Ostatné | 3 | 743 | 26.10.2010 19:53 shaggy | | Zreťazený zoznam v Assembler, C, C++, Pascal, Java | 3 | 1086 | 26.03.2012 17:06 Fico | | problem zoznam v PHP, ASP | 3 | 557 | 05.03.2008 10:33 mondzo | | Zoznam uživateľov v Redakčné systémy | 1 | 786 | 21.02.2007 11:20 Freelan | | Zoznam katalógov v Internetový marketing, SEO, reklama | 9 | 73180 | 30.12.2010 9:51 JanoF | | Zretazeny zoznam v Assembler, C, C++, Pascal, Java | 4 | 1971 | 23.02.2011 18:13 mack0 | | Python zoznam v Perl, Python, Ruby, CGI | 1 | 683 | 14.06.2013 21:35 reDo | | zoznam-program v Ostatné programy | 3 | 719 | 10.07.2008 20:07 dadmtb |
| Nemôžete zakladať nové témy v tomto fóre Nemôžete odpovedať na témy v tomto fóre Nemôžete upravovať svoje príspevky v tomto fóre Nemôžete mazať svoje príspevky v tomto fóre
|
|