[Çözüldü] Gösterici hataları "bellek yetersiz"

Başlatan noktakom, 01 Şubat 2011 - 17:21:52

« önceki - sonraki »

0 Üyeler ve 2 Ziyaretçi konuyu incelemekte.

noktakom

Aşağıdaki fonksyonu çalıştırdığımda, pc de 2,5 gb boş ram olmasına rağmen, "bellek yetersiz" uyrarısını alıyorum.

Tavsiyeniz olursa, buradayım..


#include <stdio.h>
#include <stdlib.h>

#define MAX 10

main() {

char **p;
int i;

p=(char **) malloc(sizeof(char *)*MAX);
if(p==NULL) {printf("bellek yetersiz");exit(1);}

for(i=0;i<MAX;i++) {
if(p[i]==NULL) {printf("bellek yetersiz");exit(1);}
p[i]=(char *) malloc(sizeof(char));
printf("ad:");
gets(p[i]);
}

for(i=0;i<MAX;i++) {
printf("%s\n",p[i]);
free(p[i]);
}
free(p);
}

sem

#1
Bellek ile ilgili bir sıkıntı yok.  Zaten sorunu ikinci malloc ile yaşıyorsunuz.Kodu şu şekilde yazmışsınız;

if(p[i]==NULL) {printf("bellek yetersiz");exit(1);}
p[i]=(char *) malloc(sizeof(char));


p[A] nin adresinin null olup olmadığına göre bellek yetersiz kontrolü oluşturmuşsunuz. Siz p için yer ayırdığınız için malloc'un başarısızlık durumunda NULL değeri p'ye atanıyor. Yani ilk malloc kontrolünüz doğru. p nin içeriğini (p[1,2,3]) kontrol etmek için önce hepsine ayrı ayrı yer atamalısınız daha sonra NULL kontrolü yapmalısınız. Yani aslında tek yapmanız gerken ikinci malloc fonksiyonunu if'den önce kullanmak...

Şöyle ki...
#include <stdio.h>
#include <stdlib.h>

#define MAX 10

main() {

char **p;
int i;

p=(char **) malloc(sizeof(char *)*MAX);
if(p==NULL) {printf("bellek yetersiz");exit(1);}

for(i=0;i<MAX;i++) {
p[i]=(char *) malloc(sizeof(char));
if(p[i]==NULL) {printf("bellek yetersiz");exit(1);}
printf("ad:");
gets(p[i]);
}

for(i=0;i<MAX;i++) {
printf("%s\n",p[i]);
free(p[i]);
}
free(p);
}



NOT: p[.i] yi noktasız yazınca yazı italik oluyor ondan p[A] olarak değiştiriyorum...

EK: Bir düzen getirdim daha anlaşılır yaptım yazıyı.. Ama en anlaşılırı kod olacak =)
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Tabi doğru :) ben ilk malloc 'a takılıp kalmıştım hiç ikinciye bakmak aklıma gelmedi :)

Neyse eliniz değmişken kitaptaki şu örneğe de bakabilir misiniz ? çalışmadı da... pek anlamadım zaten şu fonksyon göstericilerini :(

#include <stdio.h>

void main(void)
{
void (far *reset) (void) = (void (far *) (void) ) 0xFFFF0000;
reset();
}

sem

Bu örnek tanıdık geldi... =) programların görebildiği sanal bellek olduğu için bu tarz kodların işe yaramadığını okumuştum bir yerde...  Tam olarak ne demek istediğini bile anlamadım diyebilirim... Sadece bu kodların çalışmayacağını çıkarttım diyebilirim...

Sizde de söz dizim hatası (syntax error) mı veriyor program? Kodun çalışmamasının nedenini şöyle daha rahat görebilirsiniz;

#include <stdio.h>

void main(void)
{
void far *reset;
}



uzak, yakın ve dev göstericiler standartlarda bulunmuyor. O nedenle varsayılan kütüphanelerde tanımlanmadığını yukarıdaki kodu derleyerek aldığımız hatadan görebiliyoruz. GCC'nin verdiği hata çıktılarının nasıl bir tepki olduğunu görmek için şu kod ile kıyaslayabilirsiniz.

#include <stdio.h>

void main(void)
{
void HAKAN *reset;
}



Nasıl kullnılıyor, hala kullanılıyor mu, hangi kütüphanelerde tanımlanmış; bir fikrim yok maalesef..
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Program sözde pc'ye reset attırıyor... Kitap duruyorsa 404. sayfadan bakabilirsin...


"uzak, yakın ve dev göstericiler standartlarda bulunmuyor." Onun yerine  HAKAN göstericisini mi kullandık ?  ::) :)
#include <stdio.h>

void main(void)
{
void HAKAN *reset;
}


Derlerken aldığım hata da şöyle

$ gcc -o reset reset.c
reset.c: In function 'main':
reset.c:5:11: error: expected ')' before '*' token

sem

Hayır HAKAN isminde bir gösterici ya da tanımlayıcı yok... Demek istediğim şu idi;

reset.c
Alıntı Yap#include <stdio.h>

void main(void)
{
void  *reset;
}

Programı derlerken sorun yok... Derleme işlemi;

sem0900@ubuntu:~/Desktop$ gcc reset.c -o reset
sem0900@ubuntu:~/Desktop$


Görüldüğü gibi hata/uyarı vermeden derleniyor.

reset.c
Alıntı Yap#include <stdio.h>

void main(void)
{
void far *reset;
}

Derlerken hata var...
sem0900@ubuntu:~/Desktop$ gcc reset.c -o reset
reset.c: In function 'main':
reset.c:6: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token
reset.c:6: error: 'p' undeclared (first use in this function)
reset.c:6: error: (Each undeclared identifier is reported only once
reset.c:6: error: for each function it appears in.)
sem0900@ubuntu:~/Desktop$


Bu hata ile şu hatanın çok benzer oldğunu demek istedim;
Alıntı Yap
reset.c
void main(void)
{
void HAKAN *reset;
}

Derleme aşaması;
sem0900@ubuntu:~/Desktop$ gcc reset.c -o reset
reset.c: In function 'main':
reset.c:6: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token
reset.c:6: error: 'p' undeclared (first use in this function)
reset.c:6: error: (Each undeclared identifier is reported only once
reset.c:6: error: for each function it appears in.)
sem0900@ubuntu:~/Desktop$


HAKAN diye bir belirleyici yok... Demek istediğim standart olarak far'da yok... Derleyici HAKAN ve far için aynı tepkiyi veriyor...

Yani far kullanmak için daha farklı şeylere ihtiyaç var... Bu yakın, uzak, dev göstericiler donanım bağımlı ve sisteme göre değişiklik gösteren yapılardır. Şu şekilde diyeyim;

"80x86 mikro işlemcilerini kullanan 16 bit işletim sistemlerinde göstericiler yakın, uzak ve dev olmak üzere 3 kısma ayrılırlar. Bu nedenle yakın, uzak ve dev göstericiler yalnızca 80x86 mimarisinde çalışan derleyiciler ve özellikle de DOS işletim sistemleri için anlamlı ve geçerlidir...."

Sayfa 339 ilk cümle =)
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Kodu far kullanmadan, aşağıdaki  şekilde değiştirdim.

#include <stdio.h>

void main(void)
{
void (*reset) (void);
reset = (void(*) (void)) 0xFFFF0000 ;
reset();
}


ve çalışma esnasında
$ ./reset
Segmentation fault


hatasını aldım.

Bunun sizin de dediğiniz gibi programların görebildiği belleğin sanal bellek olmasından kaynaklandığını düşünüyorum. Bilmiyorum ne kadar doğru...

Neyse benim asıl sormak istediğim böyle kısıtlamalar varken bu tarz yani işletim sistemine emir veren veya bilgi alışverişinde bulunan yazılımları nasıl yapabiliriz ???

Örneğin; Unix tabanlı OS'lerdeki sensors komutunu 2 saniyede bir çalıştırıp, aldığı değerleri ekrana yazdıracak program nasıl yapılabilir ?

sem

Dediğim gibi bahsi geçen sanal belleğin ne olduğu hakkında bir fikrim yok. Belki de dediğiniz gibi o yüzden de olabilir. Bu bahsedilen sanal bellek hakkında fikri olan arkadaşlar yazarlarsa hep beraber öğrenmiş oluruz.

Programda reset göstericisine bir adres atanmış. Fakat bu adresin ne olduğu belli mi? Bu adres hangi program tarafından kullanılıyor... Bu şekilde atamalar daima bu hataya neden olacaktır... Göstericiler ile çalışırken bu şekilde bilinmeyen bellek bölgeleri, ilk değer verilmemiş göstericiler gibi durumlar daima hataya neden olacaktır.

Aynı hatayı aşağıdaki programı derleyerek de alabilirsiniz. Bu programda da mantıken hata yok gibi... Bir göstericiye değer atanıyor fakat göstericinin tuttuğu adres belli değil... O nedenle aynı hatayı alıyoruz.

#include <stdio.h>
void main(void)
{
char *s;
*s = 'a';
}


Ki zaten bu program çalışıp bilgisayarı yeniden başlatacak olsa bile yetki engeline takılacaktır.



Böyle kısıtlamalar ile kastınızı tam olarak anlamadım. Yalnız işletim sistemi ile çalışmak istiyorsanız bu konu biraz ileri seviye oluyor. Standart C'yi öğrendiniz diyelim. Bu şekilde öğrendikleriniz ile her sistemde çalışabilirsiniz. Windows, Linux fark etmez çünkü yazdığınız kodlar C standartlarında olmak zorunda olduğu için sistem bağımsız olacaktır.

İleri C'ye geldiğinizde ise fonksiyonlar hemen standart diyebilirim (çok bildiğim konular değil, sadece bildiğimi söylüyorum. Yani bu dediklerimi bilirkişinin sözleri değil de biraz bakınmış olan bir kişi olarak değerlendirebilirsiniz.)

Örneğin sizin telefon defterinde kullandığınız acces() fonksiyonu dosyayı kontrol ediyor. Standart C'den biraz ileri bir konu diyebiliriz. Ama Windows'ta da hemen hemen aynı komut mevcut. Yanlış hatırlamıyorsam _acces() olması lazım.. Yani fonksiyonlar bu şekilde değişiklik gösteriyor genelde.

Fonksiyonlar dışında ise C ile ileri programlarda örneğin yapılar karmaşıklaşabiliyor. "Bağlı Liste" olarak arama yaparsanız bu yapılardan birisine örnek olarak bakınmış olursunuz.

Sistem ile çalışma ise aslında bu yukarıdakileri hallettikten sonra (en azından az çok hallettikten sonra desek daha iyi olur) daha rahat kavrayabileceğiniz bir konu. Örneğin sitede yazılan programlara bakın; çok güzel uygulamalar yazılıyor, gzel kod örnekleri çıkıyor fakat "genel olarak" programların hiç birisinde paralel programlama yok. Örneğin kullanıcıdan giriş alırken, bir yandan arkada bazı işlemleri gerçekleştiren bir program yok.

Ya da uygulamalar arası haberleşme, bir programa dışarıdan nasıl müdahale edebilriz gibi gibi.. Bahsettiğiniz şeyler bunları da kapsıyor ve en az C kadar bunlara da çalışmak gerekiyor.


Ben bu şekilde düşünüyorum/biliyorum...

Tabii bahsettiğiniz programı yapmak için bunlara çok ihtiyacınız olmaz çünkü sistem ile ilgili bilmeniz gereken tek şey "sensor" komutunun varlığı. Bahsettiğiniz programı şu şekilde yazabilirsiniz;

system("sensors > sıcaklıklar");

C programında kullanacağınız bu komut sensors çıktısını, sürecin son bulunduğu dizin içerisinde "sıcaklıklar" adında bir doyaya kayıt eder. Daha sonra tek yapmanız gereken bu dosyadan okuma yapıp, dosyayı silmek...

Belirli periyot içinse sleep() fonksiyonu ve bir for döngüsü içerisinde programı yazmanız yeterli... Yani normal bildiğiniz C içerisine "sensors > sıcaklıklar" komutunu eklemiş olacaksınız o kadar...

Bunun dışıda dosyaya yazdırmadan doğrudan program içerisinden çıktıları almak için boru haberleşmesi kullanabilirsiniz bu da sistem programlamaya dahildir. İsimli borular böyle bir program için işinizi görecektir... Dosyalardan farkı azdır ama azdır....

fopen değil de popen ile açılır gibi... Farklarından da bir tane söyleyeyim; eğer ki yanlış hatırlamıyorsam; bir boru haberleşmesinde rewind() uygulanamıyordu.

Uygulama Geliştirme Ekibi'nin yazıdğı Kısayol Oluşturucu ve Mixer programları içerisinde isimli boru kullanımına örnek görebilirsiniz.
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

#8
Teşekkürler, yazdıklarınızla bana ve konuyu okuyan insanlara her zaman  yeni ufuklar açıyorsunuz.

Programı yaptım..


#include <stdio.h>

main(){
FILE *sensor;
int oku;

for(;;) {
system("clear");
printf("-------------------------------------------------------\n");
printf("Adı ve Sürümü: Yandım Anam v 1.0                       \n");
printf("İşlevi: Pc sıcaklıklarını saniyede bir kez ekrana basar\n");
printf("-------------------------------------------------------\n");
system("sensors > sıcaklıklar");
sensor=fopen("sıcaklıklar","r");
oku=fgetc(sensor);
for(;oku!=EOF;) {
putchar(oku);
oku=fgetc(sensor);
}
printf("-------------------------------------------------------\n");
remove("sıcaklıklar");
sleep(1);
}
}
}

sem

Rica ederim...

Programı test ettim bende çalışıyor... İsterseniz bu başlığı çözüldü olarak etiketleyin, sanal bellek ve uzak göstericiler konusunu

http://forum.ubuntu-tr.net/index.php/topic,24946.0.html

başlığından konuşalım... Daha doğrusu cevap bekleyelim bilen arkadaşlardan... =)
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?