Tam Sürümünü Görmek İçin : Bu kodda hata nerde?
#include <stdio.h>
#include <mysql/mysql.h>
int main(){
MYSQL *mysql;
MYSQL *connection;
mysql_init(mysql);
connection = mysql_real_connect(mysql, "localhost", "root", "", "test", 0, NULL, 0);
}
---------------------------------------------------------------------
/bin/sh: line 1: 15304 Segmentation fault ./hw
Press Enter to continue!
yanlız şu şekilde hata vermiyor
#include <stdio.h>
#include <mysql/mysql.h>
int main(){
MYSQL *mysql;
int i;
MYSQL *connection;
mysql_init(mysql);
connection = mysql_real_connect(mysql, "localhost", "root", "", "test", 0, NULL, 0);
}
Okudugum kadarıyla iki pointer ard arda tanımlanır. Peki bu kod neden hata veriyor o zaman. Benim eksik bildigim bi şeylermi var?
ergoktas
28/11/2006, 08:56
mysql init ederken mysql structure in adresini geçirmek gerekiyor sanırım ..
fonksiyon prototipi şöyle :
MYSQL *mysql_init(MYSQL *mysql)
yani kodu şu şekilde değiştirip dene istersen :
mysql_init(&mysql);
hangi derleyiciyi kullanıyorsun??
myavuzselim
28/11/2006, 15:34
http://dev.mysql.com/doc/refman/5.0/en/mysql-init.html
mysql senin kodda 'dangling pointer' olarak kalmis, yani gecerli bir hafiza alanini gostermiyor. mysql_init bu pointer'i degistiremez. Sunlari bir dene:
MYSQL *mysql;
mysql = (MYSQL*) malloc(sizeof(MYSQL)); // bunu ekle
MYSQL *connection;
mysql_init(mysql);
veya
MYSQL *mysql;
MYSQL *connection;
mysql = mysql_init(NULL);
Yanlız dikkatiniz çekmek istedigim bi nokta var iki pointer arasına bi integer tanımlarsam aynı kod gayet sağlıklı çalışıyor...
Benzer Şekilde Şu kod da düzgün çalışmıyor gibi:
#include <stdio.h>
#include <mysql/mysql.h>
#include <string.h>
#include <strings.h>
struct kisi {
char adi[];
char soyadi[];
}kisi1;
int main(){
strcpy(kisi1.adi,"AHMET");
strcpy(kisi1.soyadi,"TURKAN");
printf("ADI :%s\n",&kisi1.adi);
printf("SOYADI :%s\n",&kisi1.soyadi);
}
Çıktı :
ADI :TURKAN
SOYADI :TURKAN
Press Enter to continue!
GCC VERSİYON DÖKÜMÜ :
kervan@dellkubuntu:~$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,java,f95,objc,ada,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.0 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-java-awt=gtk-default --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-4.0-1.4.2.0/jre --enable-mpfr --disable-werror --with-tune=pentium4 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.0.3 (Ubuntu 4.0.3-1ubuntu5)
mysql = (MYSQL*) malloc(sizeof(MYSQL));
şu şekilde bellekten yer alınca çalışıyor fakat benim amacım başka şekilde kodu calıştırmak değil bu kodun neden çalışmadığını anlamak...
acehreli
29/11/2006, 01:38
Fobus, rastgele bir degeri olan bir gostergeyi kullandigin icin "tanimsiz davranisla" (undefined behavior) karsi karsiyasin. Oyle yaptigin zaman ne olacagini standart "tanimlamamistir".
Boyle bir duruma dustugunde programin calismasi konusunda hicbir sey soyleyemeyiz.
Araya bir int yerlestiginde de tanimsiz davranistan kurtuluyor degilsin. HAlA tanimsiz davranis; ama o durumda program tesadufen senin beklentin dogrultusunda calisiyor.
Baskalarinin da soyledigi gibi, koddaki hatan mysql'in hicbir MYSQL nesnesini gostermiyor olmasinda. mysql_init'e ya yine daha once konusuldugu gibi malloc ile ayrilan yeri gondereceksin; ya da yerel bir MYSQL nesnesinin adresini gondereceksin:
MYSQL mysql; // <-- yerel nesne
mysql_init(&mysql); // <-- adresini gonderiyoruz
O durumda mysql_real_connect'e de &mysql gondermek gerekecek...
Tabii mysql baska bir yapinin parcasi da olabilir:
struct BenimYapim
{
MYSQL mysql;
/* ... */
};
void BenimYapim_init(struct BenimYapim * yapim)
{
mysql_init(&(yapim->mysql));
/* ... */
}
void foo()
{
struct BenimYapim yapim;
BenimYapim_init(&yapim);
/* ... */
}
Oteki programdaki hatalar da, strcpy'e gosterdigin hedefte (kisi1.adi) kaynaktaki karakterlerin sigacagi kadar yer olmamasinda. strcpy gibi dizgi islevlerini kullanirken islemlerin sonuclarinin sigacaklarindan emin olman gerekir.
Ali
o zaman şurada hata var.
http://www.ceviz.net/index.php?case=article&id=637&catid=13
acehreli
29/11/2006, 02:04
Evet, orada hata var :)
Ali
Uzun süredir makalenin yorumlarına bakamıyordum.Öncelikle bu hata için üzgün olduğumu söyliyeyim.Arkadaşların söylediği gibi çözüm için ya mysql değişkenine belirli bir kullanım alanı açmak gerekiyor yada
MYSQL mysql;
MYSQL *connection;
mysql_init(&mysql);
connection = mysql_real_connect(&mysql, "localhost", "uname", "upass", "dname", 0, NULL, 0);
şeklinde <<acehreli>> nin de belirttiği gibi bağlantının nesnesel adresinide fonksiyona sunmak gerekiyor.Tekrar tekrar özür dilerim bu hata için.En kısa zamanda makaleyi güncelleyeceğim.
Abiler siz daha iyi bilirsiniz ama bi fikrim var sorun şunda galiba
MYSQL *mysql;
MYSQL *connection;
Pointer lar ilk oluşturuluğunda ilk değer atamak faydalı bir alışkanlıktır. Bazı derleyicilerde pointeri Null a eşitledik mi bu tip hatalar çözülüyor. Belli ki ilk kullanıma kalkışıldığı yere kadar pointerler bellekte gerçekten oluşturulmuyo, ve ilk kullanıma hazırlandığı yer de bir atama işlemi varsa kıyametler kopuyor. Bi deneyip sonucu söylerseniz doğru mu düşünüyorum ilginize teşekkürler.
acehreli
27/12/2006, 19:54
mr_c, isaretciler tanimlandiklari yerde olusturulurlar. Ilk kullanildiklari yerde ozel bir sey yapilmaz.
Ilk deger olarak NULL'in kullanilmasinin nedeni, o ozel degerin "gecersiz isaretci" anlamina gelmesidir. Uygun bir deger atamadan kullanirsak bu hatamizi gorebilelim diye.
Ali
Teknik olarak dediğiniz doğru ama pratikte değil. Denediğim birçok derleyicide işaretçiyi ilk tanımladığım yerde ilkdeğer ataması yapmazsam bu tip hatalar aldım. C derleyicilerinin bellek yöentimiyle alakalı bir durum yani.
Yukarıda bahsedilen kodda bir int tanımlaması yapılınca programın çalışma nedeni ne o zaman?
Yani ilk değer ataması yapılmadığı taktirde bellekte yer ayrılmıyor tuhaf bir şekilde.
MYSQL *mysql=null;
MYSQL *connection=null; yaparak programda sorun çözülür gibi geliyor deneyip söylermisiniz?
acehreli
27/12/2006, 21:25
Isaretcileri ilk deger atamadan kullanmak cok bilinen bir hatadir. Standart bu durumda ne olacagini acik bir sekilde tanimsiz birakir. Soyle bir sey soyler: Ilk degeri atanmayan isaretciyi kullanmak tanimsiz davranistir.
Ama isaretcilerin ilk degerleri, onlarin tanimlandiklari yerde bilinmeyebilirler. Isaretcilerin degerlerini daha sonradan atamak zorunda kalabiliriz. Onun icin, bu hatayi "ilk degeri atanmayan isaretci kullanmak" yerine, "herhangi bir nesneyi gostermeyen isaretciyi kullanmak" olarak tanimlamak daha dogru olur.
Tanimsiz davranisi denemek de olanaksizdir. Ne olacagi belli olmaz. Bir sonraki denemede farkli bir sonuc cikabilir.
Yukaridaki kodda int tanimlaninca programin calismasi da tanimsiz davranisin bir ornegidir. Bu durumda ne olacagi tanimlanmadigi icin, davranis, program dogru calisiyor gibi olusabilir. Burada da bu oluyor.
MYSQL *mysql=null;
satirinin anlami sudur: 'mysql' hicbir nesneyi gostermeyen ama programda daha sonraki bir noktada bir MYSQL nesesini gosterecek olan bir isaretcidir. Yani, bu noktada tanimladik ama henuz bir MYSQL'i gostermiyor.
Onun icin, mysql'i program icinde bu haliyle kullanamayiz.
Ali
Sözylemek istediğimi tam anlatamadım sanırım. İşaretçilere ilk değer atamak ve atamamak ve nedenleri hakkında haklısınız. Demek istediğim şu:
İlk verilen ve kodda hata mesajı vermesiyle ilgili durumdan bahsediyorum. Kanımca sorun şu, ik değer atamadığımız taktirde işaretçiyi kullanmaya başladığımız durumda sorun yaşıyoruz. Nedenine gelince işaretçi tanımlandığı halde işaretçiyi kullandığımız anda ancak oluşturuluyor bu da istenmeyen bellek hatası oluşturuyor.
Ama sizin bahsettiğiniz hata şeklinde değil. Sizin bahsettiğiniz ilk oluşturduğumuzda gösterdiği adres belli değil her yer olabilir. Benim bahsettiğim biyeri işaret edecek bir işaretçinin olmaması durumu.
Şöyleki işaretçi tanımlandığı halde kullanmaya başlayana kadar gerçekte var olmuyor. Teorik olarak bu mümkündeğil. Ama pratikte mümkün.
Neden? Cevap OPTIMIZASYON! Derleyici derleme işlemi sırasında bu tip bir davranış sergiliyor. Verileri optimize ediyor ve ilk kullanıldığı yere kadar asla oluşturmuyor. Bu C nin beklenen davranışı değil, derleyicden kayanklı.
Bu durumda
1. Optimizasyon seçeneğini kapatarak derlersek sorun çözülebilir
2. İlk değer ataması yaparsak. ( Optimize de edilse ilk değer atandığı için işaretçi varolur.)
Şimdi anlatabilmişimdir umarım. Derleyince düzelip düzelmediğini öğrenmeden bunu yazmak istemezdim ama cevap gelmedi.
acehreli
27/12/2006, 22:58
Bastaki koddaki isaretcilerin olusturulmasi, program yigit yazmacinin (stack register) degerinin azaltilmasindan ibarettir. mysql yerel bir nesne oldugu icin, pratikte onun yeri program yigitidir (program stack). Bunu programin assembly ciktisinda gorebiliriz.
Bahsettigin optimizasyon, derleme sirasinda yapilir. Derleyici, kullanilmayan isaretci icin yigitta yer ayirmayabilir. Eger dogru anliyorsam, sen "kullandigi an" derken calisma zamanindan bahsediyorsun. O isaretciyi "olusturan" kod, derleme zamaninda olusturulan bir kodla (bir cikartma islemi) yigitin bir yerinin onun icin ayrilmasi anlamindadir.
Bunun dinamik bellekten yer ayirmak kadar kulfetli oldugunu dusunmemek gerek: hicbir "ayirma" islemi yapilmaz bile; mysql olarak yalnizca yigitin bir noktasina erisilir.
1) Sorun optimizasyon secenegini kapatinca cozulmez cunku mysql_init, isini yapabilmek icin kendisine bir MYSQL nesnesinin adresinin verilmesini ister. Optimizasyon secenegi ile ilgisiz olarak, programda boyle bir nesne yok.
2) Ilk deger atamasi yapmak yeterli degildir, cunku her deger bir MYSQL nesnesinin adresi degildir. Ornegin ilk deger olarak NULL olmaz. 0x1000 de olmaz, herhangi baska bir deger de olmaz. Ancak bir MYSQL nesnesinin adresi olur.
[Ara not: Aslinda malloc ile ayrilan yer, yerin ayrildigi anda bir MYSQL nesnesi degildir. O bellek bolgesi MYSQL nesnesi kimligini mysql_init cagrildiktan sonra kazanir.]
Bahsedilen yazinin yazari uszr'nin de kabul ettigi gibi, burada mysql_init'e (tabii mysql_real_connect'e de) gecerli bir MYSQL'in adresini vermemiz gerekir.
Daha once yazildilar ama kolaylik olsun diye tekrarliyorum... Bu durumda en basiti sudur:
MYSQL mysql; // <-- yerel bir nesne
mysql_init(&mysql); // <-- onun adresini kullaniyoruz
Burada gerek olmasa da, nesnenin yasam surecini kendimiz belirlemek istedigimizde:
MYSQL * mysql = (MYSQL*)malloc(sizeof(MYSQL));
mysql_init(mysql);
/* mysql'in gosterdigi nesneyi kendi istedigim zaman sonlandirabilirim */
Nesneyi isaretcisini tanimladigim zaman olusturmuyorsam:
MYSQL * mysql = NULL; // "Hicbir nesneyi gostermiyor" anlaminda
/* daha sonra bir noktada */
mysql = (MYSQL*)malloc(sizeof(MYSQL));
mysql_init(mysql);
Sen su kodu denememizi istiyorsun degil mi:
MYSQL *mysql=null;
mysql_init(mysql);
Denedigimi ve sonucta bekledigimiz gibi calistigini soylersem o kodun dogru oldugunu mu dusuneceksin? Bence oyle dusunmemelisin cunku o kodun davranisi tanimsizdir (undefined behavior).
Dogru calisiyor gibi gorunse bile hatali oldugunu anlamamiz gerek: mysql_init, kendisine verilen MYSQL adresini bir MYSQL nesnesi olarak kullanima hazirlayan bir islevdir. Biz ona NULL verirsek, mysql_init o adrese erisecektir. Ama NULL'da gecerli bir MYSQL yoktur...
Ali
#include <stdio.h>
#include <mysql/mysql.h>
int main(){
MYSQL *mysql;
MYSQL *connection;
mysql_init(mysql);
connection = mysql_real_connect(mysql, "localhost", "root", "", "test", 0, NULL, 0);
}
---------------------------------------------------------------------
/bin/sh: line 1: 15304 Segmentation fault ./hw
Press Enter to continue!
yanlız şu şekilde hata vermiyor
#include <stdio.h>
#include <mysql/mysql.h>
int main(){
MYSQL *mysql;
int i;
MYSQL *connection;
mysql_init(mysql);
connection = mysql_real_connect(mysql, "localhost", "root", "", "test", 0, NULL, 0);
}
Okudugum kadarıyla iki pointer ard arda tanımlanır. Peki bu kod neden hata veriyor o zaman. Benim eksik bildigim bi şeylermi var?
Sanırım derleyici gcc ama hata RT mi derleyici mi belli değil. Bu tip hataları google da aratınca yüzlercesini gördüm.
İkinci durumda kod doğru çalışmış belirtilene göre. Yani int i; tanımlamasının buradaki etkisi ne?
Derleyici derlerken int i; için bellek ayırırken diğer işaretçilere de bellek ayırıyor optimize edemiyor. Fakat bu tanımlama yoksa optimize ediyor. Ve bu da bellekte hataya neden oluyor.
Bildiğiniz gibi int *a; dediğimiz de tam sayı bir işaretçi oluşturma talimatı veriyoruz adreslere karışmıyoruz. Aynı şekişde MYSQL de bir sınıf yada typdef ile tanımlı bir veri tipi bu durumda MYSQL in adresinden bahsetmiyoruz "int" in adresinden bahsetmediğimiz gibi.
Biz ilk değer ataması yaparak bellekte verinin oluşmasına zorluyoruz. Ama veri oluştuğu an bizim verdiğimiz ilk değer değil oluştuğu bellek adresi yükleniyor. İşaretçilere özgü bir durum.
Bu hatayı her aldığımda ilk değer atadığımda durum düzeldi. Programın tam kodu olmadığından burada düzeldiğini söyleyemem. Yani sorun optimizasyon.
C den beklenen davranışı sergilememesi alıştığım bir durum scanf ile ilgili bir örnek vermek istiyorum. Tartışmak için en basit girdi çıktı işleminde neler yapıyor insan şaşırıyor.
İlginize teşekkürler sonuçta ikimizde bellek ayırma sorunu varlığında hem fikiriz buna ben optimizasyon siz yer ayırmak için komut kullanılmaması olarak yaklaşıyorsunuz. Kodun tamamı olmayınca da ikimizin teorisi de askıda.
Saygılar.
myavuzselim
28/12/2006, 15:55
MYSQL *mysql=null;
mysql_init(mysql);
Denedigimi ve sonucta bekledigimiz gibi calistigini soylersem o kodun dogru oldugunu mu dusuneceksin? Bence oyle dusunmemelisin cunku o kodun davranisi tanimsizdir (undefined behavior).
Anlattiginiz konuyla alakasi olmasa da: http://dev.mysql.com/doc/refman/5.0/en/mysql-init.html
mysql_init null parametresi aldiginda kendisi dinamik bellekten yer ayirip gecerli bir MYSQL nesnesi donduruyormus. Ama sonucta burada bizim mysql degiskenimiz hala null.
Teşekkürler link gayet güzel. İlginize de ayrıca teşekkür ederim.
acehreli
29/12/2006, 00:27
myavuzselim'in gosterdigine bakilirsa talihsiz bir ornek secmisim. :( mysql_init'in NULL aldiginda nasil davrandigi gayet guzelce tanimlanmis... :)
Onun icin temel olmasi icin su programi oneriyorum:
typedef struct
{
int sayi;
} BenimTurum;
void foo(BenimTurum * isaretci)
{
isaretci->sayi = 42;
}
int main()
{
BenimTurum * isaretci;
foo(isaretci);
}
Boyle bir programda main icinde 'isaretci'ye ilk deger atanmamis olmasi nedeniyle tanimsiz davranisla karsi karsiyayiz. Ilk deger olarak NULL kullanilmasi da durumu degistirmez, cunku NULL gecerli bir BenimTurum isaretcisi degildir.
[myavuzselim'in belirttigine gore, benim foo'mun yerine mysql_init kullaninca bir sorun yok, cunku mysql_init NULL gelince nesneyi kendisi olusturuyormus.]
mr_c, isaretcilere ozgu oldugunu soyledigin durumu gosteren bir kaynak verebilir misin? Soylediklerinden sanki isaretci nesneleri icin ozel bir sey yapiliyormus gibi bir anlam cikiyor. Ben bu gune kadar boyle bir bilgiyle karsilasmadim. Bunlari kendi gozlemlerine dayanarak mi soyluyorsun, yoksa bir kaynagin var mi?
Senin gozlemlerinle dusunduklerin birbirleriyle uyusuyor olabilirler ama bu noktada kaynaklara bakarak ne derece hakli oldugunu arastirman gerekiyor. Cunku su soylediklerin yanlis: (Bunlarin yanlisliklarini bir derleyicinin assembly dokumlerinde gosterecegim)
1) YANLIS: "Ilk deger atamasi yaparak bellekte verinin olusmasini zorluyoruz."
Bak bu programda isaretci adli isaretciye ilk deger atanmiyor ama kendisi yasiyor:
void foo(int **);
int main()
{
int * isaretci;
foo(&isaretci);
}
void foo(int **)
{}
isaretci'nin yasadigi yer 401005h adresidir: (0040103F adresindeki isleme bak)
int main()
{
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,0Ch
00401026 mov dword ptr [ebp-0Ch],0CCCCCCCCh
0040102D mov dword ptr [ebp-8],0CCCCCCCCh
00401034 mov dword ptr [ebp-4],0CCCCCCCCh
int * isaretci;
foo(&isaretci);
0040103B lea eax,[isaretci]
0040103E push eax
0040103F call foo (401005h)
00401044 add esp,4
}
foo icinde isaretci'nin kullanilmiyor olmasi da bu durumu degistirmez, cunku foo'nun cagrildigi noktada derleyici foo'yu gormez. (foo baska bir derleme biriminde (translation unit) tanimlanmis olabilir.)
Simdi isaretci'ye bir ilk deger atayalim: (Programi kisa tutmak icin NULL'un esdegeri olan 0 degerini kullaniyorum.)
void foo(int **);
int main()
{
int * isaretci = 0;
foo(&isaretci);
}
void foo(int **)
{}
Tek fark, isaretci'nin bulundugu adrese (401005h) 0 degerinin yazilmis olmasi:
int main()
{
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,0Ch
00401026 mov dword ptr [ebp-0Ch],0CCCCCCCCh
0040102D mov dword ptr [ebp-8],0CCCCCCCCh
00401034 mov dword ptr [ebp-4],0CCCCCCCCh
int * isaretci = 0;
0040103B mov dword ptr [isaretci],0
foo(&isaretci);
00401042 lea eax,[isaretci]
00401045 push eax
00401046 call foo (401005h)
0040104B add esp,4
}
Yani bellekte verinin olusmasi diye bir durum yok. YIgItIn bir noktasi (401005h adresi) isaretci olarak dusunulmus ve kullaniliyor.
2) YANLIS: "Veri olustugu an bizim verdigimiz ilk deger degil, olustugu bellek adresi yukleniyor."
Programda isaretciye istedigi degeri programci verir ve o deger programci degistirene kadar durur. Bunun herhangi baska bir tUr nesneye yapilan atama isleminden bir farki yoktur. Yani nasil bir int'in ilk degeri kendisine yeni bir deger ataninca kalmiyorsa, isaretcinin degeri de gider. Hicbir fark yok...
#include <stdio.h>
void foo(int **);
int main()
{
int sayi = 42;
int * isaretci = 0;
printf("%p\n", isaretci);
// Burada ne yaparsak yapalim isaretci'nin degeri 0 kalacaktir. (Eger
// programda hatalar varsa, istemeden isaretci'nin uzerine
// yazilabilir. Boyle hatalardan bahsetmiyorum.)
// Basit bir atama islemi, isaretcilere ozel hicbir davranis yok:
isaretci = &sayi;
printf("%p\n", isaretci);
// Ayni sekilde, burada ne yaparsak yapalim isaretci'nin degeri
// sayi'nin adresi olacaktir.
foo(&isaretci);
}
void foo(int **)
{}
Asagida 00402735 adresinde isaretci'ye 0 degeri ataniyor (ilk degeri). Daha sonra 00402757 adresinde sayi'nin adresi okunuyor ve 0040275A adresinde bu deger isaretci'ye ataniyor.
int main()
{
00402710 push ebp
00402711 mov ebp,esp
00402713 sub esp,18h
00402716 push esi
00402717 mov eax,0CCCCCCCCh
0040271C mov dword ptr [ebp-18h],eax
0040271F mov dword ptr [ebp-14h],eax
00402722 mov dword ptr [ebp-10h],eax
00402725 mov dword ptr [ebp-0Ch],eax
00402728 mov dword ptr [ebp-8],eax
0040272B mov dword ptr [ebp-4],eax
int sayi = 42;
0040272E mov dword ptr [sayi],2Ah
int * isaretci = 0;
00402735 mov dword ptr [isaretci],0
printf("%p\n", isaretci);
0040273C mov esi,esp
0040273E mov eax,dword ptr [isaretci]
00402741 push eax
00402742 push offset __load_config_used+48h (404688h)
00402747 call dword ptr [__imp__printf (4071DCh)]
0040274D add esp,8
00402750 cmp esi,esp
00402752 call _RTC_CheckEsp (401110h)
// Burada ne yaparsak yapalim isaretci'nin degeri 0 kalacaktir. (Eger
// programda hatalar varsa, istemeden isaretci'nin uzerine
// yazilabilir. Boyle hatalardan bahsetmiyorum.)
// Basit bir atama islemi, isaretcilere ozel hicbir davranis yok:
isaretci = &sayi;
00402757 lea ecx,[sayi]
0040275A mov dword ptr [isaretci],ecx
printf("%p\n", isaretci);
0040275D mov esi,esp
0040275F mov edx,dword ptr [isaretci]
00402762 push edx
00402763 push offset __load_config_used+4Ch (40468Ch)
00402768 call dword ptr [__imp__printf (4071DCh)]
0040276E add esp,8
00402771 cmp esi,esp
00402773 call _RTC_CheckEsp (401110h)
// Ayni sekilde, burada ne yaparsak yapalim isaretci'nin degeri
// sayi'nin adresi olacaktir.
foo(&isaretci);
00402778 lea eax,[isaretci]
0040277B push eax
0040277C call foo (401014h)
00402781 add esp,4
}
isaretci'nin yerini gormek icin yine bir foo cagrisi yaptim. 0040277C adresindeki isleme bakarak isaretci'nin 401014h adresinde yasadigini goruyoruz.
Goruyor musun, hicbir "veri olusturma" olayi yok. 401014h adresi 'isaretci' adli nesne olarak dusunuluyor ve dogrudan onun icine yaziliyor ve oradan okunuyor.
3) YANLIS: "Isaretcilere ozgu bir durum."
Bunu zaten yukarida gosterdim... Isaretcilere ozgu bir sey yok. Isaretcilerin de degerleri vardir; bu degerler programci tarafindan gerektigi zaman atanabilir. Bazen ilk degersiz birakilabilir; ama o durumda isaretcinin kullanilmasi tanimsiz davranisa neden olur.
Ali
"volatile" keyword ü ne demektir. Hangi durumlarda kullanılması önerilir?
acehreli
30/12/2006, 03:04
'volatile', derleyiciye sunun gibi bir sey soyler: "gorebildigin kadar koda bakarak bu nesnenin degerinin degismeyecegini sanma; degeri senin goremedigin bir kod tarafindan degistiriliyor olabilir; bu yuzden, onun degerini bir yazmacta saklamak yerine, her erisimde o nesneden dogrudan oku."
Bir kullanim alani, bir donanim yazmacindaki degerleri okumaktir. volatile kullanmadigimiz zaman derleyici yazmacin degerinin program boyunca degismeyecegini sanarak her erisimde ilk okudugu degeri kullanabilir.
Bir nesnenin degeri, derleyici aksinden emin olsa bile coklu isletim dizileri bulunan bir ortamda da degisebilir.
Ali
Bir nesnenin degeri, derleyici aksinden emin olsa bile coklu isletim dizileri bulunan bir ortamda da degisebilir.Ali
Baştan beri bunu anlatmaya çalışıyorum, optimizasyon etkisi diye. Varsayalım optimizasyon ve işletim sistemi davranışı değil.
Öyleyse bu anahtar kelimeye neden gereksinim duyulmuş. Değişkenin durumunun değişebileceğinden neden şüphelenmiş?
Özellikle optimizasyon kelimesinden kaçınarak cevap vermişsimiz. :) Tebrik ediyorum. Ancak C kullanıcıları bı kadar alternatif çözüm bulabilir.
Not: Sistem saati güncellemesi örneğini vermeyiniz.
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.