Obsah fóra
PravidláRegistrovaťPrihlásenie




Odpovedať na tému [ Príspevkov: 12 ] 
AutorSpráva
Offline

Užívateľ
Užívateľ
Obrázok užívateľa

Registrovaný: 17.08.12
Prihlásený: 02.01.15
Príspevky: 94
Témy: 29
Príspevok NapísalOffline : 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. chyba

Vž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
Offline

Skúsený užívateľ
Skúsený užívateľ
Obrázok užívateľa

Registrovaný: 13.11.07
Prihlásený: 20.08.16
Príspevky: 1702
Témy: 0
Príspevok NapísalOffline : 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.


Offline

Užívateľ
Užívateľ
Obrázok užívateľa

Registrovaný: 17.08.12
Prihlásený: 02.01.15
Príspevky: 94
Témy: 29
Príspevok Napísal autor témyOffline : 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
Offline

Skúsený užívateľ
Skúsený užívateľ
Obrázok užívateľa

Registrovaný: 13.11.07
Prihlásený: 20.08.16
Príspevky: 1702
Témy: 0
Príspevok NapísalOffline : 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.


Offline

Užívateľ
Užívateľ
Obrázok užívateľa

Registrovaný: 17.08.12
Prihlásený: 02.01.15
Príspevky: 94
Témy: 29
Príspevok Napísal autor témyOffline : 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
Offline

Skúsený užívateľ
Skúsený užívateľ
Obrázok užívateľa

Registrovaný: 13.11.07
Prihlásený: 20.08.16
Príspevky: 1702
Témy: 0
Príspevok NapísalOffline : 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á.


Offline

Užívateľ
Užívateľ
Obrázok užívateľa

Registrovaný: 17.08.12
Prihlásený: 02.01.15
Príspevky: 94
Témy: 29
Príspevok Napísal autor témyOffline : 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
Offline

Skúsený užívateľ
Skúsený užívateľ
Obrázok užívateľa

Registrovaný: 13.11.07
Prihlásený: 20.08.16
Príspevky: 1702
Témy: 0
Príspevok NapísalOffline : 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.


Offline

Užívateľ
Užívateľ
Obrázok užívateľa

Registrovaný: 17.08.12
Prihlásený: 02.01.15
Príspevky: 94
Témy: 29
Príspevok Napísal autor témyOffline : 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
Offline

Skúsený užívateľ
Skúsený užívateľ
Obrázok užívateľa

Registrovaný: 13.11.07
Prihlásený: 20.08.16
Príspevky: 1702
Témy: 0
Príspevok NapísalOffline : 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é.


Offline

Užívateľ
Užívateľ
Obrázok užívateľa

Registrovaný: 17.08.12
Prihlásený: 02.01.15
Príspevky: 94
Témy: 29
Príspevok Napísal autor témyOffline : 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
Offline

Skúsený užívateľ
Skúsený užívateľ
Obrázok užívateľa

Registrovaný: 13.11.07
Prihlásený: 20.08.16
Príspevky: 1702
Témy: 0
Príspevok NapísalOffline : 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.


Odpovedať na tému [ Príspevkov: 12 ] 


Podobné témy

 Témy  Odpovede  Zobrazenia  Posledný príspevok 
V tomto fóre nie sú ďalšie neprečítané témy. Spajany zoznam , C#

v Technológia .NET

2

1440

06.12.2010 18:10

walther Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. Spajany zoznam C

v Assembler, C, C++, Pascal, Java

2

1937

28.04.2015 22:24

JanoF Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. C - spajany zoznam struktur - help

v Assembler, C, C++, Pascal, Java

2

393

02.05.2014 19:29

TieSTiK Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. Jednosmerny spajany zoznam struktur v C

v Assembler, C, C++, Pascal, Java

7

1778

08.05.2013 15:28

BX Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. Zoznam

v JavaScript, VBScript, Ajax

1

1863

25.06.2012 0:08

shaggy Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. zoznam

v HTML, XHTML, XML, CSS

10

2274

05.08.2007 10:20

HAE07 Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. zoznam

v HTML, XHTML, XML, CSS

17

2946

23.06.2007 22:06

sento Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. zoznam moderatorov

v Redakčné systémy

10

912

23.08.2006 19:38

gumy Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. zoznam kontaktov

v Ostatné

3

743

26.10.2010 19:53

shaggy Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. Zreťazený zoznam

v Assembler, C, C++, Pascal, Java

3

1086

26.03.2012 17:06

Fico Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. problem zoznam

v PHP, ASP

3

557

05.03.2008 10:33

mondzo Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. Zoznam uživateľov

v Redakčné systémy

1

786

21.02.2007 11:20

Freelan Zobrazenie posledných príspevkov

Táto téma je zamknutá, nemôžete posielať nové príspevky alebo odpovedať na staršie. Zoznam katalógov

v Internetový marketing, SEO, reklama

9

73180

30.12.2010 9:51

JanoF Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. Zretazeny zoznam

v Assembler, C, C++, Pascal, Java

4

1971

23.02.2011 18:13

mack0 Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. Python zoznam

v Perl, Python, Ruby, CGI

1

683

14.06.2013 21:35

reDo Zobrazenie posledných príspevkov

V tomto fóre nie sú ďalšie neprečítané témy. zoznam-program

v Ostatné programy

3

719

10.07.2008 20:07

dadmtb Zobrazenie posledných príspevkov


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

Skočiť na:  

Powered by phpBB Jarvis © 2005 - 2024 PCforum, webhosting by WebSupport, secured by GeoTrust, edited by JanoF
Ako väčšina webových stránok aj my používame cookies. Zotrvaním na webovej stránke súhlasíte, že ich môžeme používať.
Všeobecné podmienky, spracovanie osobných údajov a pravidlá fóra