[ svoo @ 23.03.2005. 16:58 ] @
Ovaj program bi treabao da ucitava odredjen broj stringova, smjesta na heap te prebrojava koliko puta je svaki od strignva unesen. Uspio sam da ga kompajliram i pokrenem ali cim pocjem nesto unositi on javlja gresku, nesto kao:
"The instruction at "0x7802.." referenced memory at "0x....". The memory could not be "written"l

kod je slijedeci:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
typedef struct Lista{
char* element;
Lista* next;
int br;
}Lista_Rijeci;
void ucitaj_NizRijeci(Lista_Rijeci*);
void ispisi_NizRijeci(Lista_Rijeci*);
void insert(char*,Lista_Rijeci*);//Pomocna Funkcija
typedef Lista_Rijeci* point;
main()
{
Lista_Rijeci* Prvi=0; ;
ucitaj_NizRijeci(Prvi);


getchar();
}
void insert(char* str,Lista_Rijeci*pok){
int pom=0;
if(!pok){pok==(point)malloc(sizeof(Lista_Rijeci));
strcpy(pok->element,str);
pok->br=1;
pok->next=0;
}
while(pok!=0)
{
if(!strcmp(str,pok->element))
{
pok->br++;
pom=1;
}
if(pom)break;
else
pok=pok->next;
}

if(pom){
pok->next=(point)malloc(sizeof(Lista_Rijeci));
strcpy(pok->next->element,str);
pok->br=1;
pok->next->next=0;
}
}
void ucitaj_NizRijeci(Lista_Rijeci* pok){
char* pomocni;
do
{
gets(pomocni);
insert(pomocni,pok);
if(!strcmp(pomocni,"0"))break;

}
while(pomocni[0]);
}
void ispisi_NizRijeci(Lista_Rijeci*pok){
while(pok!='\0')
{
puts(pok->element);
printf(" %d",pok->br);
printf("\n");
pok=pok->next;
}
}

Unaprijed hvala na pomoci.
[ deroko @ 23.03.2005. 17:34 ] @
Nisam do detalja nalizirao ali sam ti otklonio greske koje su prouzrkovale pad:
* sam markirao ono sto sam ja promenio

Code:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
typedef struct Lista{
       char *element;
       Lista* next;
       int br;
}Lista_Rijeci;

void ucitaj_NizRijeci(Lista_Rijeci*);
void ispisi_NizRijeci(Lista_Rijeci*);
void insert(char*,Lista_Rijeci*);//Pomocna Funkcija
typedef Lista_Rijeci* point;

int main(){
       Lista_Rijeci* Prvi=0; ;
       ucitaj_NizRijeci(Prvi);


       getchar();
}

void insert(char* str,Lista_Rijeci*pok){
       int pom=0;
       if(!pok){
*              pok=(point)malloc(sizeof(Lista_Rijeci));
*              pok->element = (char *)malloc(256);
              strcpy(pok->element,str);
              pok->br=1; 
              pok->next=0;
       } 

while(pok!=0){
       if(!strcmp(str,pok->element)){
              pok->br++;
              pom=1;
       }
       if(pom)
              break;
       else
              pok=pok->next;
}

if(pom){
       pok->next=(point)malloc(sizeof(Lista_Rijeci)); 
*       pok->next->element =(char *) malloc(256);
       strcpy(pok->next->element,str);
       pok->br=1;
       pok->next->next=0;
}
}
void ucitaj_NizRijeci(Lista_Rijeci* pok){
       char* pomocni;
       pomocni = (char *)malloc(10000);
       do{
              gets(pomocni);
              insert(pomocni,pok);
              if(!strcmp(pomocni,"0"))break;
       }while(pomocni[0]);
}


void ispisi_NizRijeci(Lista_Rijeci*pok){
*       while(pok){
              puts(pok->element);
              printf(" %d",pok->br);
              printf("\n");
              pok=pok->next;
       }
}


Dakle greska ti je ovde->
nemozes na char * da kopiras string ako taj cahr ne pokazuje na neku adresu u ovom slucaju moras sa malloc da lociras memoriju na koju ce *element da pokazuje kako bi mogao da kopiras string tamo.
Takodje ovo poslednje while je lepse kad ide sa
while (pok) umesto while (pok != 0 )
i koristi code tag drugi put :) ovo je bas bilo neprijatno tabovati i lepo prepisati :)
[ blaza @ 23.03.2005. 17:46 ] @
Citat:
The memory could not be "written"
Program pokusava da izmeni sadrzaj memorijskih lokacija kojima inace nema odobren pristup - obicno se radi o pointeru koji nije dobro inicijalizovan, ili pointeru koji pokazuje na prostor koji je prethodno dealociran. Hint: dangling pointer.
Obrati paznju na liniju:
Code:
 if(!pok){pok==(point)malloc(sizeof(Lista_Rijeci));

Imas jedno = viska.
Greske ces uvek najlakse otkloniti ako upotrebom debug podrske analiziras kod, liniju po liniju.
Drugi put kod koji postujes uokviri [code] [/code] tagovima, posto se na taj nacin cuva indentacija koda.
[ deroko @ 23.03.2005. 23:13 ] @
E sve si mu reko samo ne kako da natera program da radi... Niti gde mu je greska...
[ svoo @ 24.03.2005. 00:58 ] @
E ljudi primjedbe su na mjestu. Novi sam na forumu pa nisam obratio paznju na code tag-ove.
Deroko hvala na prepravci. Zanima me dali je kod alociranja moguce prosliediti kao argument tacnu duzinu stringa koji se upisuje a ne fiksno 256.
Sto se tice "==" mala nepaznja kod paste-ovanja.

[ blaza @ 24.03.2005. 04:54 ] @
Za razliku od tebe, deroko, meni je tesko da citam kod koji nema indentaciju, pa nisam ni pokusavao da analiziram isti. Ukazao sam svoo-u na prirodu greske, i rekao sam mu kako da je otkloni.
Kad vec volis da filozofiras, objasni mi zasto je
Code:
pok->element = (char *)malloc(256);

bolje od
Code:
pok -> element = (char*) malloc(strlen(str) + 1);
, i sta se desava u slucajevima kada je str vece duzine od 255.
Izbegavajte upotrebu magic numbers u kodu.
[ caboom @ 24.03.2005. 05:45 ] @
hm, ovo je podjednako los primer ako negde u kodu nemas proveru ili forsiranje '\0' terminiranih "stringova". nije bas dobar primer safe koda.
[ blaza @ 24.03.2005. 07:59 ] @
Aye, but...
Ako niz karaktera nekim slucajem nije terminiran '\0' karakterom, najgore sto moze da se desi je da se alocira vise memorije nego sto je u stvari potrebno. Pod uslovom da je rasploziva memorija dovoljno velika, uvek ce se alocirati dovoljno veliko parce memorije, tako da ctrcpy nece prouzrokovati access violation error.

Edit: ipak postoji sansa da strlen izazove Read Access Violation.
[ deroko @ 24.03.2005. 11:29 ] @
svoo : mozes i strlen da koristis da bi dobio blok memorije :)
blaza : ako oces da naklapas o buffer overflowu imas lepo Security Coding, ovo je samo pocetnicki primer i prost primer zasto program nije hteo da radi...
[ caboom @ 24.03.2005. 14:33 ] @
Citat:
blaza: Aye, but...
Ako niz karaktera nekim slucajem nije terminiran '\0' karakterom, najgore sto moze da se desi je da se alocira vise memorije nego sto je u stvari potrebno. Pod uslovom da je rasploziva memorija dovoljno velika, uvek ce se alocirati dovoljno veliko parce memorije, tako da ctrcpy nece prouzrokovati access violation error.

Edit: ipak postoji sansa da strlen izazove Read Access Violation.


paa... najgore sto moze da se desi jeste da ti "program" radi veoma cudno posto ces baratati junk informacijama. sa neterminiranim stringovima je uvek bilo zabavno, pogotovo u slozenijim komadima sw-a.
[ svoo @ 24.03.2005. 22:23 ] @
Zasto nece da radi bez linije koju sam oznacio? Valjda bi gest trebao da sam radi alokaciju jer mu je to osnovna svrha - ili grijesim?


Code:



void ucitaj_NizRijeci(Lista_Rijeci** pok){
       
       char* pomocni;
       pomocni=(char*)malloc(1000); //<-oznacena linija.
       do{
              gets(pomocni);
              insert(pomocni,*pok);
              if(!strcmp(pomocni,"exit"))break;
       }while(pomocni[0]);
}



[ deroko @ 25.03.2005. 00:30 ] @
Moras da alociras memoriju, ja ne znam nijednu funkciju u C koja sama alocira memoriju. Osim malloc normalno :)
ili da alociras sa malloc ili da pravis niz kao lokalnu ili globalnu pormenljivu, ali da ne smore zli vuci oko buffer overflowa, koristi malloc i nema glava da te boli.