Prethodna tema :: Sljedeća tema |
Autor/ica |
Poruka |
Kazo Forumaš(ica)
Pridružen/a: 10. 12. 2002. (18:46:58) Postovi: (E)16
|
Postano: 18:57 sri, 19. 1. 2005 Naslov: Vezane liste |
|
|
U namjeri da napokon pocnem vjezbati c, nabavio sam Microsoft Visual Studio .NET 2003, i napravio svoju prvu vezanu listu (jeeee). Kao i obicno, prvo sto mi je debuger javio bio je error koji kaze "Run-Time Check Failure #2 - Stack around the variable 'upis' was corrupted." Posto mi program izgleda logicki dobro napisan, ne znam zasto mi javlja gresku. Ovo je c-p programa:
#include "stdafx.h"
typedef struct __podaci
{ char ime[10];
int starost;
char drzava[10];
struct __podaci *next;
} podaci;
podaci *upis(void)
{
podaci *pnovi,*pglava,*pkraj;
char p_ime[10],p_drzava[10],upis='d';
int p_starost;
pglava=pkraj=pnovi=NULL;
printf("Upis podataka u listu");
printf("\n-------------------");
while((upis)!='k')
{
pnovi=(podaci*)malloc(sizeof(podaci));
if (pnovi==NULL) {
printf("\nNema dovoljno memorije!!");
exit(1);
}
printf("\nUpisi ime: "); scanf("%s",&p_ime); strcpy(pnovi->ime,p_ime);
printf("\nUpisi starost: "); scanf("%d",&p_starost); pnovi->starost=p_starost;
printf("\nUpisi drzavu: "); scanf("%s",&p_drzava); strcpy(pnovi->drzava,p_drzava);
if (pglava==NULL) pglava=pnovi=pkraj;
else {
pkraj->next=pnovi;
pkraj=pnovi;
}
printf("\n\nNovi upis (k za kraj)"); scanf("%s",&upis);
}
return pglava;
}
void ispis(podaci *pglava)
{
podaci *ppomocni;
if(pglava==NULL) {
printf("\n\nLista ne postoji");
return;
}
printf("\nSadrzaj liste:");
printf("\n----------------");
for(ppomocni=pglava;ppomocni!=NULL;ppomocni=ppomocni->next)
{
printf("\nIspis imena: %s",pglava->ime);
printf("\nIspis starosti: %d",pglava->starost);
printf("\nIspis drzave: %s",pglava->drzava);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
podaci *upis();
void ispis(podaci *);
podaci *m_podaci;
m_podaci=upis();
ispis(m_podaci);
return 0;
}
Molim vas da mi kazete sto nije u redu! Hvala i oprostite na velikom postu 8)
U namjeri da napokon pocnem vjezbati c, nabavio sam Microsoft Visual Studio .NET 2003, i napravio svoju prvu vezanu listu (jeeee). Kao i obicno, prvo sto mi je debuger javio bio je error koji kaze "Run-Time Check Failure #2 - Stack around the variable 'upis' was corrupted." Posto mi program izgleda logicki dobro napisan, ne znam zasto mi javlja gresku. Ovo je c-p programa:
#include "stdafx.h"
typedef struct __podaci
{ char ime[10];
int starost;
char drzava[10];
struct __podaci *next;
} podaci;
podaci *upis(void)
{
podaci *pnovi,*pglava,*pkraj;
char p_ime[10],p_drzava[10],upis='d';
int p_starost;
pglava=pkraj=pnovi=NULL;
printf("Upis podataka u listu");
printf("\n-------------------");
while((upis)!='k')
{
pnovi=(podaci*)malloc(sizeof(podaci));
if (pnovi==NULL) {
printf("\nNema dovoljno memorije!!");
exit(1);
}
printf("\nUpisi ime: "); scanf("%s",&p_ime); strcpy(pnovi→ime,p_ime);
printf("\nUpisi starost: "); scanf("%d",&p_starost); pnovi→starost=p_starost;
printf("\nUpisi drzavu: "); scanf("%s",&p_drzava); strcpy(pnovi→drzava,p_drzava);
if (pglava==NULL) pglava=pnovi=pkraj;
else {
pkraj→next=pnovi;
pkraj=pnovi;
}
printf("\n\nNovi upis (k za kraj)"); scanf("%s",&upis);
}
return pglava;
}
void ispis(podaci *pglava)
{
podaci *ppomocni;
if(pglava==NULL) {
printf("\n\nLista ne postoji");
return;
}
printf("\nSadrzaj liste:");
printf("\n----------------");
for(ppomocni=pglava;ppomocni!=NULL;ppomocni=ppomocni→next)
{
printf("\nIspis imena: %s",pglava→ime);
printf("\nIspis starosti: %d",pglava→starost);
printf("\nIspis drzave: %s",pglava→drzava);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
podaci *upis();
void ispis(podaci *);
podaci *m_podaci;
m_podaci=upis();
ispis(m_podaci);
return 0;
}
Molim vas da mi kazete sto nije u redu! Hvala i oprostite na velikom postu
_________________ Nepoznato je suvišno običnom čovjeku. Suvišno je stoga što on nema dovoljno energije da bi to pojmio.
- Carlos Castaneda
|
|
[Vrh] |
|
vsego Site Admin
Pridružen/a: 06. 10. 2002. (22:07:09) Postovi: (3560)16
Spol:
Lokacija: /sbin/init
|
|
[Vrh] |
|
Kaz0 Gost
|
|
[Vrh] |
|
pecina Forumaš(ica)
Pridružen/a: 19. 01. 2005. (14:15:23) Postovi: (157)16
Spol:
Lokacija: Happily traveling through space since 1986!
|
|
[Vrh] |
|
vsego Site Admin
Pridružen/a: 06. 10. 2002. (22:07:09) Postovi: (3560)16
Spol:
Lokacija: /sbin/init
|
Postano: 17:23 čet, 20. 1. 2005 Naslov: |
|
|
[quote="Kaz0"][quote="vsego"]Molim, koristiti code-blokove. 8)[/quote]
to je bio copy-paste, pa zbog toga nema blokova[/quote]
Kakve to veze ima? :-s
Evo, ovo radi pod GCCom:
[code:1]#include <stdlib.h>
#include <stdio.h>
typedef struct __podaci
{ char ime[10];
int starost;
char drzava[10];
struct __podaci *next;
} podaci;
podaci *upis(void)
{
podaci *pnovi,*pglava,*pkraj;
char p_ime[10],p_drzava[10],upis='d';
int p_starost;
pglava=pkraj=pnovi=NULL;
printf("Upis podataka u listu");
printf("\n-------------------");
while((upis)!='k')
{
pnovi=(podaci*)malloc(sizeof(podaci));
if (pnovi==NULL) {
printf("\nNema dovoljno memorije!!");
exit(1);
}
printf("\nUpisi ime: "); scanf("%s",&p_ime); strcpy(pnovi->ime,p_ime);
printf("\nUpisi starost: "); scanf("%d",&p_starost); pnovi->starost=p_starost;
printf("\nUpisi drzavu: "); scanf("%s",&p_drzava); strcpy(pnovi->drzava,p_drzava);
if (pglava==NULL)
pglava=pkraj=pnovi;
else
{
pkraj->next=pnovi;
pkraj=pnovi;
}
printf("\n\nNovi upis (k za kraj)"); scanf("%s",&upis);
}
pkraj->next=NULL;
return pglava;
}
void ispis(podaci *pglava)
{
podaci *ppomocni;
if(pglava==NULL) {
printf("\n\nLista ne postoji");
return;
}
printf("\nSadrzaj liste:");
printf("\n----------------");
for(ppomocni=pglava;ppomocni!=NULL;ppomocni=ppomocni->next)
{
printf("\nIspis imena: %s",ppomocni->ime);
printf("\nIspis starosti: %d",ppomocni->starost);
printf("\nIspis drzave: %s",ppomocni->drzava);
}
}
int main(int argc, char* argv[])
{
podaci *upis();
void ispis(podaci *);
podaci *m_podaci;
m_podaci=upis();
ispis(m_podaci);
return 0;
}[/code:1]
[quote="pecina"]Nedostaje[code:1]free(m_podaci);[/code:1][/quote]
Ovo bi oslobodilo samo "glavu". :roll: Ako zeli cistiti memoriju, onda treba protrcati po cijeloj listi:
[code:1]for(ppomocni=pglava;ppomocni!=NULL;ppomocni=pnext)
{
pnext=ppomocni->next;
freemem(ppomocni);
}[/code:1]
8)
Kaz0 (napisa): | vsego (napisa): | Molim, koristiti code-blokove. |
to je bio copy-paste, pa zbog toga nema blokova |
Kakve to veze ima?
Evo, ovo radi pod GCCom:
Kod: | #include <stdlib.h>
#include <stdio.h>
typedef struct __podaci
{ char ime[10];
int starost;
char drzava[10];
struct __podaci *next;
} podaci;
podaci *upis(void)
{
podaci *pnovi,*pglava,*pkraj;
char p_ime[10],p_drzava[10],upis='d';
int p_starost;
pglava=pkraj=pnovi=NULL;
printf("Upis podataka u listu");
printf("\n-------------------");
while((upis)!='k')
{
pnovi=(podaci*)malloc(sizeof(podaci));
if (pnovi==NULL) {
printf("\nNema dovoljno memorije!!");
exit(1);
}
printf("\nUpisi ime: "); scanf("%s",&p_ime); strcpy(pnovi->ime,p_ime);
printf("\nUpisi starost: "); scanf("%d",&p_starost); pnovi->starost=p_starost;
printf("\nUpisi drzavu: "); scanf("%s",&p_drzava); strcpy(pnovi->drzava,p_drzava);
if (pglava==NULL)
pglava=pkraj=pnovi;
else
{
pkraj->next=pnovi;
pkraj=pnovi;
}
printf("\n\nNovi upis (k za kraj)"); scanf("%s",&upis);
}
pkraj->next=NULL;
return pglava;
}
void ispis(podaci *pglava)
{
podaci *ppomocni;
if(pglava==NULL) {
printf("\n\nLista ne postoji");
return;
}
printf("\nSadrzaj liste:");
printf("\n----------------");
for(ppomocni=pglava;ppomocni!=NULL;ppomocni=ppomocni->next)
{
printf("\nIspis imena: %s",ppomocni->ime);
printf("\nIspis starosti: %d",ppomocni->starost);
printf("\nIspis drzave: %s",ppomocni->drzava);
}
}
int main(int argc, char* argv[])
{
podaci *upis();
void ispis(podaci *);
podaci *m_podaci;
m_podaci=upis();
ispis(m_podaci);
return 0;
} |
pecina (napisa): | Nedostaje |
Ovo bi oslobodilo samo "glavu". Ako zeli cistiti memoriju, onda treba protrcati po cijeloj listi:
Kod: | for(ppomocni=pglava;ppomocni!=NULL;ppomocni=pnext)
{
pnext=ppomocni->next;
freemem(ppomocni);
} |
_________________ U pravilu ignoriram pitanja u krivim topicima i kodove koji nisu u [code]...[/code] blokovima.
Takodjer, OBJASNITE sto vas muci! "Sto mi je krivo?", bez opisa u cemu je problem, rijetko ce zadobiti moju paznju.
|
|
[Vrh] |
|
pecina Forumaš(ica)
Pridružen/a: 19. 01. 2005. (14:15:23) Postovi: (157)16
Spol:
Lokacija: Happily traveling through space since 1986!
|
Postano: 17:27 čet, 20. 1. 2005 Naslov: |
|
|
Kako loš kod :evil: :evil: :evil:
Evo normalne verzije:
[code:1]#include <cstdio>
#include <cstring>
#include <malloc.h>
#include <cstdlib>
#include <tchar.h>
struct podaci
{
char ime[10];
int starost;
char drzava[10];
struct podaci *next;
};
podaci *upis(void)
{
podaci *pnovi = 0, *pglava = 0, *pkraj = 0;
char p_ime[10] = "\0", p_drzava[10] = "\0";
int p_starost = 0;
printf("Upis podataka u listu");
printf("\n-------------------");
while(1)
{
pnovi = (podaci*)malloc(sizeof(podaci));
pnovi->next = 0;
if (!pnovi)
{
// nije bogzna potrebno
printf("\nNema dovoljno memorije!!");
exit(1);
}
printf("\nUpisi ime: ");
scanf("%s",p_ime);
if (!strcmp(p_ime, "end"))
break;
strcpy(pnovi->ime,p_ime);
printf("\nUpisi starost: ");
scanf("%d",&p_starost);
pnovi->starost=p_starost;
printf("\nUpisi drzavu: ");
scanf("%s",p_drzava);
strcpy(pnovi->drzava,p_drzava);
if (!pglava)
pglava = pkraj = pnovi;
else
{
pkraj->next = pnovi;
pkraj = pnovi;
}
}
return pglava;
}
void ispis(podaci *pglava)
{
podaci *ppomocni = 0;
if (!pglava)
{
printf("\n\nLista ne postoji");
return;
}
printf("\nSadrzaj liste:");
printf("\n----------------");
for(ppomocni=pglava; ppomocni; ppomocni = ppomocni->next)
{
printf("\nSadrzaj ppomocni : %x", ppomocni);
printf("\nIspis imena: %s",ppomocni->ime);
printf("\nIspis starosti: %d",ppomocni->starost);
printf("\nIspis drzave: %s",ppomocni->drzava);
}
}
int main(int argc, _TCHAR* argv[])
{
podaci *m_podaci = 0;
m_podaci=upis();
ispis(m_podaci);
podaci *temp = 0;
while (m_podaci)
{
temp = m_podaci->next;
free(m_podaci);
m_podaci = temp;
}
return 0;
}
[/code:1]
Greška je bila u:[code:1]pnovi=(podaci*)malloc(sizeof(podaci));[/code:1]
Naime, MSVC inicijalizira novostvoreni memorijski prostor sa 0xCDCDCDCD tako da se lako uoče greške. Varijabla novi je imala nedefiniranu vrijednost umjesto 0. Tako je kod[code:1]ppomocni = ppomocni->next[/code:1]u jednom trenutku otisao na neku memorijsku lokaciju koja nema smisla.
Dakle pouka:
[b]1. Uvijek inicijalizirajte varijable. Čak i one trivijalne
2. Koristite C++, jer u konstruktoru možete resetirati pointere[/b]
Još jedan hint: Mnogi C developeri imaju zgodan trik koji glasi[code:1]neka_struktura *pPtr = (neka_struktura*)malloc(sizeof(neka_struktura));
ZeroMemory(pPtr, sizeof(neka_struktura));[/code:1]
gdje je ZeroMemory definiran kao
[code:1]#define ZeroMemory(a) memset(a, 0, neka_struktura);[/code:1]
Kako loš kod
Evo normalne verzije:
Kod: | #include <cstdio>
#include <cstring>
#include <malloc.h>
#include <cstdlib>
#include <tchar.h>
struct podaci
{
char ime[10];
int starost;
char drzava[10];
struct podaci *next;
};
podaci *upis(void)
{
podaci *pnovi = 0, *pglava = 0, *pkraj = 0;
char p_ime[10] = "\0", p_drzava[10] = "\0";
int p_starost = 0;
printf("Upis podataka u listu");
printf("\n-------------------");
while(1)
{
pnovi = (podaci*)malloc(sizeof(podaci));
pnovi->next = 0;
if (!pnovi)
{
// nije bogzna potrebno
printf("\nNema dovoljno memorije!!");
exit(1);
}
printf("\nUpisi ime: ");
scanf("%s",p_ime);
if (!strcmp(p_ime, "end"))
break;
strcpy(pnovi->ime,p_ime);
printf("\nUpisi starost: ");
scanf("%d",&p_starost);
pnovi->starost=p_starost;
printf("\nUpisi drzavu: ");
scanf("%s",p_drzava);
strcpy(pnovi->drzava,p_drzava);
if (!pglava)
pglava = pkraj = pnovi;
else
{
pkraj->next = pnovi;
pkraj = pnovi;
}
}
return pglava;
}
void ispis(podaci *pglava)
{
podaci *ppomocni = 0;
if (!pglava)
{
printf("\n\nLista ne postoji");
return;
}
printf("\nSadrzaj liste:");
printf("\n----------------");
for(ppomocni=pglava; ppomocni; ppomocni = ppomocni->next)
{
printf("\nSadrzaj ppomocni : %x", ppomocni);
printf("\nIspis imena: %s",ppomocni->ime);
printf("\nIspis starosti: %d",ppomocni->starost);
printf("\nIspis drzave: %s",ppomocni->drzava);
}
}
int main(int argc, _TCHAR* argv[])
{
podaci *m_podaci = 0;
m_podaci=upis();
ispis(m_podaci);
podaci *temp = 0;
while (m_podaci)
{
temp = m_podaci->next;
free(m_podaci);
m_podaci = temp;
}
return 0;
}
|
Greška je bila u: Kod: | pnovi=(podaci*)malloc(sizeof(podaci)); |
Naime, MSVC inicijalizira novostvoreni memorijski prostor sa 0xCDCDCDCD tako da se lako uoče greške. Varijabla novi je imala nedefiniranu vrijednost umjesto 0. Tako je kod Kod: | ppomocni = ppomocni->next | u jednom trenutku otisao na neku memorijsku lokaciju koja nema smisla.
Dakle pouka:
1. Uvijek inicijalizirajte varijable. Čak i one trivijalne
2. Koristite C++, jer u konstruktoru možete resetirati pointere
Još jedan hint: Mnogi C developeri imaju zgodan trik koji glasi Kod: | neka_struktura *pPtr = (neka_struktura*)malloc(sizeof(neka_struktura));
ZeroMemory(pPtr, sizeof(neka_struktura)); |
gdje je ZeroMemory definiran kao
Kod: | #define ZeroMemory(a) memset(a, 0, neka_struktura); |
|
|
[Vrh] |
|
pecina Forumaš(ica)
Pridružen/a: 19. 01. 2005. (14:15:23) Postovi: (157)16
Spol:
Lokacija: Happily traveling through space since 1986!
|
|
[Vrh] |
|
Kaz0 Gost
|
|
[Vrh] |
|
mdoko Forumaš(ica)
Pridružen/a: 30. 11. 2002. (22:17:12) Postovi: (71A)16
Spol:
Lokacija: Heriot-Watt University, Edinburgh
|
|
[Vrh] |
|
pecina Forumaš(ica)
Pridružen/a: 19. 01. 2005. (14:15:23) Postovi: (157)16
Spol:
Lokacija: Happily traveling through space since 1986!
|
|
[Vrh] |
|
Kaz0 Gost
|
|
[Vrh] |
|
pecina Forumaš(ica)
Pridružen/a: 19. 01. 2005. (14:15:23) Postovi: (157)16
Spol:
Lokacija: Happily traveling through space since 1986!
|
|
[Vrh] |
|
|