|
[ miskec @ 24.03.2005. 11:18 ] @
| Ljudi imam jedan glupi probelm sa pointer funkcijom i nemam pojma kako da ga resim a treba mi htino. Evo ovako. Kreirao sam funkciju koja glasi:
Code:
char *Funkcija1(int Broj)
{
if(Borj == 1)
{
return "Ja sam programer":
}else
{
return "Ja sam samarac";
}
}
E sad u glavnom delu programa negde u kodu imam sledece linije za poizvanjeove funkcije i ispisivanje porukue.
Slucaj 1:
Code:
char *Prvo;
char *Drugo;
Prvo = Funckija(1);
MessageBox(NULL, Prvo, "Poruka", MB_OK);
U prvom slucaju sve strava radi. Upali se Message Box i ispise mi se u njemu "Ja sam programer".
E sad Slucaj 2 je onaj koji meni treba i koji pravi probel. A to je"
Code:
char *Prvo;
char *Drugo;
Prvo = Funckija(1);
Drugo = Funkcija1(0);
MessageBox(NULL, Prvo, "Poruka", MB_OK);
MessageBox(NULL, Drugo, "Poruka", MB_OK);
Naime sta nije uredu. U slucaju 2 se ucita u pointer Prvo prva poruka a u pointer drugo druga poruka. Medjutim kad ispisem u Message Boxu i u prvom i u drugom msgboxu ispise se ista druga poruka "Ja sam smarac".
Ja znam da je to zbog toga sto je prva funkcija pointer i da se ova dva pointera (prvi i drugi) izjednace sa njim i pokazuju na istu vrednost u memoriji koja je ili prva ili druga poruka. A posto pokazuju na isto mesto u memoriji uvek su isti kad se menja jedan menja se idrugi.
E sad treba mi htino kako da resim ovaj probelm da ubacim to lepo da mi ispise obe poruke u ova dva Message Box ali da koristim ovako neke promenljive posrdne kao sto su Prva i Druga a ne da direktno pisem MessageBox(NULL, Funkcija1(1), "poruka", MB_OK);
Nadam se da me kapirate treba mi pomoc hitno |
[ deroko @ 24.03.2005. 11:45 ] @
Code:
#include <windows.h>
#include<stdio.h>
char *Funkcija1(int);
char* Funkcija1(int Broj){
if(Broj == 1)
return "Ja sam programer";
return "Ja sam samarac";
}
int main(){
char *Prvo;
char *Drugo;
Prvo = Funkcija1(1);
Drugo = Funkcija1(0);
MessageBox(NULL, Prvo, "Poruka", MB_OK);
MessageBox(NULL, Drugo, "Poruka", MB_OK);
return 0;
}
Greske u kodu nema, osim toga sto si napamet prekucao kod pa sam morao da ispravljam :)))
Radi bas onako kako si i zamislio, jedan MB stampa "Ja sam programer" drugi, "Ja sam smarac", greske u kodu nema (osim sintaksnih)...
I drugo funkcija ti nije pointer nego funckija koja vraca obican DWORD koji C tretira kao char * iliti u ovom slucaju pointer na adresu stringova koji se nalaze u .data sectionu PE-EXE fajla mapiranog u memoriji :)
Poz...
[ obranko @ 25.03.2005. 23:51 ] @
Pozdrav,
izbegavaj ovako da kodiras. problem koji imas je da vracas pointer na lokalnu varijabla. ovo ponekad nije lako otkriti, moze sa desiti da kod tebe sve radi ok a kod drugih da ne radi kako treba.
u tvom slucaju alocirao si memoriju za odgovor "ja sam programer" i vratio pointer na tu memoriju. kada si ponovo pozvao istu funkciju samo sa drugim parametrom funkcija je ponovo alocirala istu memoriju za odogovor "ja sam nesto drugo" i vratila ti isti pointer kao i u prvom slucaju.
za duzi zivot i bolje zivce izbegavaj da vracas pointere na lokalne promenljive.
[ deroko @ 26.03.2005. 01:28 ] @
Auuuu bre kakve crne lokalne promenljive, kakvo alociranje memorije :)))
Nista od toga :) Uvek ce vracati konstantne pointere na podatke sadrzane u sectionu gde se kriju podaci (najcesce se zove DATA ili .data u PE-EXE fajlu) :)
[ NastyBoy @ 26.03.2005. 01:41 ] @
Citat: izbegavaj ovako da kodiras. problem koji imas je da vracas pointer na lokalnu varijabla. ovo ponekad nije lako otkriti, moze sa desiti da kod tebe sve radi ok a kod drugih da ne radi kako treba
Da se ne ponavljamo, ovo je poenta!
NIKAD, NIKAD, NIKAD ne vracaj pointere na lokalne varijable! Zato se i zovu lokalne, chim napustish scope varijable, ta varijabla vishe nije validna.
.data section PE fajla nije nikakav izgovor za najrudimentarniju greshku u alociranju memorije i radu sa pointerima!
[ deroko @ 26.03.2005. 02:16 ] @
ajoj pa jer vi pravite razliku izmedju :
Code:
char buf[20]="deroko"; //glup primer inicijalizovanja lokalne promenljive :)
i
Code:
char *buf="deroko";
mislim stvarno :)
Ahhh vidim da ce neko morati da obnavlja gradivo iz Ca :))))
Uzgred gde vi vidite lokalne promenljive u Funkcija1(int Broj); ja ih bogme nigde ne vidim, vidim samo argument koji se predaje funkciji i nista vise...
[ NastyBoy @ 26.03.2005. 03:20 ] @
Citat: Uzgred gde vi vidite lokalne promenljive u Funkcija1(int Broj); ja ih bogme nigde ne vidim, vidim samo argument koji se predaje funkciji i nista vise...
Tachno, navedeni stringovi nisu lokalne promenljive.
Moj komentar se odnosio na generalni sluchaj zabune oko alokacije memorije (const data/heap/stack/free-storage/global-static), a i nisam siguran da li je postavljach teme napravio razliku, i da li mu je jasna ta razlika.
Izvod iz knjige Herb Sutter-a, a koji se odnosi na gornji problem :
Citat: Const Data
The const data area stores string literals and other data whose values are known at compile-time. No objects of class type can exist in this area.
All data in this area is available during the entire lifetime of the program. Further, all this data is read-only, and the results of trying to modify it are undefined.
This is in part because even the underlying storage format is subject to arbitrary optimization by the implementation. For example, a particular compiler may choose to store string literals in overlapping objects as an optional optimization.
Nadam se da ovo pojashnjava pomenuti problem.
[Ovu poruku je menjao NastyBoy dana 26.03.2005. u 04:21 GMT+1]
[ caboom @ 26.03.2005. 03:20 ] @
sta ako zoves Funkcija1() mnogo puta?
[frustrations](p.s. generalno se u C-u alokacija (bez obzira u kom segmentu i na koji nacin) na "dnu" bez predavanja pointera koji ce pokazivati na taj segment smatra prljavom i verovatno bi zavrsio sa nekim static-om i proverom da li je NULL, sto bi ti bilo koji iskusniji sistem arhitekta vratio nazad na prepisivanje - nazalost nagledao sam se takvog koda u poslednje vreme)[/frustrations]
[ deroko @ 26.03.2005. 10:37 ] @
caboom : zovi je koliko oces puta, ovo nije alociranje memorije niti sta drugo vec jednostavno ovo ce se assemblovati ovako na x86 a i na drugim platformama ce biti isto s tim sto ce se koristiti drugi registri i drugacije instrukcije.
Code:
.data
string1 db "Ja sam programer", 13, 10 ,0
string2 db "Ja sam smarac", 13, 10, 0
...
.code
__start:
push 1
call Funkcija1
push 0deadc0deh
call Funkcija1
Funkcija1:
arg1 equ dword ptr[esp+4]
cmp arg1, 1
je __jedno
mov eax, offset string1
jmp __exit
__jedno:
mov eax, offset string2
__exit: ret 4
Dakle ovu funkciju mogu pozvati koliko ocu, bez brige da ce me boleti glava :)
NastBoy : ok, ja sam se ogranicio na konkretan primer a ne na vracanje adrese lokalnih promenljivih neke fje :) To je svakako pogresno :):))
[ caboom @ 26.03.2005. 14:24 ] @
zapravo u pravu si... cak i da se mnogo puta pozove to biva optimizovano na slican nacin, postajem nepazljiv. :)
[ deroko @ 26.03.2005. 14:57 ] @
Pa ovu funkciju Funkcija1 koju sam ja dao mozes da pozoves recimo ovako gde je N = beskonacno i ima da radi uvek dok ne pobenavi kompjuter :
Code:
for (;;){
Prvo = Funkcija1(1);
Drugo = Funkcija1(0);
MessageBox(NULL, Prvo, "Poruka", MB_OK);
MessageBox(NULL, Drugo, "Poruka", MB_OK);
}
Ovaj tvoj primer jeste ruzan, ali on ce uvek raditi, jer alocirana memorija na heapu se ne unistava pri izlasku iz fje, vec tek konacno kad program pozove free(); ili kako ja to radim na kraju ExitProcess() sistem ce sam da ocisti svu memoriju koju je program koristio i tu nema memory leak. Drugo je pitanje kad pises glomaznu aplikaciju onda bi moj savet iso da se predaje pointer na vec alociranu memoriju. Jer bi ovakvo pozivanje funkcije zasigurno dovelo do preteranog punjenja memorije :) Mislim da si mozda na to ciljao :)
[ caboom @ 26.03.2005. 14:59 ] @
ma obrisao primer, skontao sam sta se desava kada sam asemblovao neki drugi kod i pogledao sta se desava. moja greska... :) fora je sto su danasnji kompajleri dovoljno "pametni" da ne prave gresku koja je meni pala na pamet.
[ deroko @ 26.03.2005. 15:02 ] @
:)))) Nema frke, ko radi taj i gresi :)))
Ziveli C kompajleri :)))
[ caboom @ 26.03.2005. 15:15 ] @
fora je sto nikada nisam pogledao sta se desava u slucaju koji si pomenuo - npr. for(;;), ispostavlja se da se, suprotno mojim ocekivanjima, sve lepo sredi. barem sa gcc-om i vc++-om (barem u ovim vremenima kada imamo zaista solidne kompajlere).
[ deroko @ 26.03.2005. 19:07 ] @
i bcc32 i bcc32 :))) ne zaboravimo na njega :))
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|