C++'da Bellek yönetimi

Başlatan yamak, 08 Temmuz 2014, 09:45:38

yamak

C++'ın bellek yönetimi hakkında iki adet sorum olacaktı:
1. Sınıf içinde tanımladığımız attribute lar nesne'ni ömrü kadardır.Peki bu attribute lar Data segmentte mi tutulur yoksa stack'te mi?Bu durum nesnenin global ya da local olma durumuna göe değişir mi?

2. Bir sınıf tanımlarken .h dosyasında da başka sınıfılardan yeni nesneler oluşturdum diyelim.Bu nesneleri kurucu metodlarını parametre aktarımını nasıl yaparım.İllaki .h dosyasında o pointer olarak tanımlayıp kurucu mettoda mı allocate etmem gerekiyor.Örnek olarak A ve B adında iki sınıfım olsun:

class A
{
   public:
   A(int x=1,int y=1);
   .....
   private:
   .....
};

class B
{
   public:
   B();
   A a_nesnesi;
   private:
   ..... 
};


Şimdi burda a_nesnesi ben a_nesnesi(5,4) olarak tanımlamak istersem ne yapmam gerekiyo.illaki
A* a_nesnesi;

olarak tanımlayıp B'nin kurucu metodunda
a_nesnesi=new A(5,4);

olarak allocate etmem mi gerekiyo.

bocek

#1
1. sorunun cevabını bilmiyorum
2. soru :
class B
{
   public:
   B() { a_nesnesi.x = 5; a_nesnesi.y = 4; };
   A a_nesnesi;
   private:
   ..... 
};


şeklinde tanımlaman yeterli.

ayrıca A'yı tanımlarken ilkdeğer vermek için şöyle de yapabilirsin:
class A
{
   public:
   A():x(1),y(1) {};
   .....
   private:
   .....
};


eğer A* a_nesnesi;
deyip
a_nesnesi=new A(5,4) dersen bu sefer B'nin yıkıcı fonksiyonunda ,
delete a_nesnesi;
demen gerekir. yoksa bellek sızıntısı oluşur.

yani
class B
{
   public:
   B() { a_nesnesi = new A(5,4); };
   ~B() { delete a_nesnesi; };
   A* a_nesnesi;
   private:
   ..... 
};
1 ya da 0. işte 'bit'ün mesele..

yamak

#2
Sağolun hocam o şekilde bi kullanımdan haberim yoktu.Fakat ilk söylediğiniz yöntemin çalışması için x ve y nin public olarak tanımlanması gerekmez mi?

Edit:Şimdi kodunuzu inceledim de siz benim sorumu yanlış anladığınız galiba.Mesela aşağıdaki gibi bir kodda a_nesnesini kurucu fonksiyonunu nasıl çağırırım.

class B
{
   public:
   B();
   A a_nesnesi;
   private:
   ..... 
};

Eğer cevabı 1. verdiğiniz cevapsa onun çalışması  yukarıda da bahsettiğim gibi x ve y nin public olarak tanımlanması gerekir.Yani constructor ın parametrelerine o şekilde erişilemez.

bocek

#3
x ve y'nin public ya da private olduğunda dair bir bilgi yok kodlarında. ama private olduğunu söylüyorsun o zaman haklısın. erişilemez.
o zaman şöyle yapalım:
class A
{
   public:
   A(int a=1,int b=1) { x=a; y=b;}; // x ve y'ye fonksiyon parametre tanımı içinde ilkdeğer verilmez. 
 // yani yalnızca A(x=1,y=1) deyince üye x=1 ve üye y=1 olmaz.
   .....
   private:
   int x,y;
   .....
};

class B
{
   public:
   B(): a_nesnesi(5,4) {};
   A a_nesnesi;
   private:
   ..... 
};
1 ya da 0. işte 'bit'ün mesele..

yamak

#4
Evet bu şekilde oldu.Değişkenlere bu şekilde değer verildiğini biliyodum. Ama nesnelerin kurucu fonksiyonlarının bu şekilde  çalıştırılabildiklerini bilmiyodum.
1. sorunun cevabını hala merak ediyorum.Bilen birisi aydınlatırsa güzel olur.

z

@Gerbay

Alıntı Yapburada "add       esp,-16" kısmında stack pointer (esp) a eksi on altı ekleniyor. aslında bu "sub esp, 16" ile aynı ama toplama daha hızlı olduğu için "sub" yerine "add" üretiyor compilerımız burada....

ADD komutu SUB komutundan daha hizli degil. Bu sadece bir yazim sitili ve buradaki olay kodun biraz daha  anlasilirligini saglamak.

ESP, Stack alaninda kullanilabilir adresi gosteriyor. Simdi biz bu alana 16 byte veri yerlestireceksek  SP 16 byte geriyi gosterecek sekilde azaltmaliyiz. Yani  SUB  ESP,16

Fakat ADD  ESP,-16  stack alaninda yapilan islemi gorme acisindan daha anlasilir.

Cunku adresleme asagida gorulecegi uzere stackda geriye  (yuksek adreslerden kucuk adreslere) dogru yerlesecek sekilde ebp-nn  seklinde adresleniyor.

    mov       dword ptr [ebp-16],10
    mov       dword ptr [ebp-12],11
    mov       dword ptr [ebp-8],80
    mov       dword ptr [ebp-4],25

ADD'in SUB'dan hizli oldugunu nerede okudun?

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Bahsettigin BP+ofset islemi kacinilmaz.

Fonksiyon cagrilmadan once a,b,c degiskenleri stacka atiliyor ve ardindan fonksiyon cagiriliyor.

Bu asamada SP degeri BP e aktarildiginda BP artik relatif sifir noktamiz.

Bp-n degerleri ile fonksiyon degiskenlerine, BP+m ile de fonksiyon parametrelerine ulasiyoruz.

Haliyle BP + m gibi adresleme yapilmasi cok normal.

Dedigim gibi bu sadece bir yazim sitili. Ofset degerimize pozitif ve negatif degerler ekleyerek degisken adresleri elde etmek bana daha okunakli geliyor.

Yoksa ADD ve SUB, makine saykili sayisi acisindan tamamen esdeger komutlar.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Olsun, hata ayiklama vs acisindan ASM ciktisinin yakisikli olmasi guzel bir sey.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

yamak

Hocam çok teşkkür ederim.Resem kitap gibi olmuş.
Hocam global ve static instance'lar için BSS yer ayrılmasının nedeni initialize edilmemiş olarak kabul edilmesi mi?Yani kurucu metod'da parametre versem de nesneler initialize edilmemiş mi oluyo ?
Bir de hocam bu konuları açıklandığı önerebileceğiniz güzel bi C++ kitabı var mı?Geçenlerde C++ How to Program kitabını aldım.Ama kitapta bu konulara pek girilmemiş.

z

Alıntı yapılan: gerbay - 09 Temmuz 2014, 11:24:09
hocam orada debug yapılırken asm üzerinden gidilmiyor.

keşke cortex için derleseymişim, konu nereye gitti..

Konuyu dallandırdığımın farkındayım ama debug aşamasında elbette asm üzerinden gidilecek.

Kod sahibi sizseniz sorun yok ama sadece exe sahibiyseniz ve programı debug edecekseniz göreceğimiz kodlar elbette bu kodlar olacak. Zaten yazım stili de bu aşamada anlaşılırlığı kolaylaştıracak.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

yamak

#10
Anladım hocam.
Peki hocam local olarak  tanımlanmış bir nesneye ait attributeları kurucu metotda da initialize etmezsek.Ayni c'de ki attribute lar 0 a initialize edilmez değil mi? Eğer edilmezse kafamı karıştıran bir durum oldu.Denemek için Qt'de Mainwindow sıfında bi tane değişken tanımladım ve bu değişkenin değerini initialize etmeden bi tane lineEdit e yazdırdım ve sonuç 0 çıktı.Mainwindow'dan object instance'ı aşağıdaki gibi main fonksiyonunun içinde oluşturulmuş.
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Bu durum tesadüf mü?Yoksa local olarak tanımlanmış nesnelerin attribute ları da 0 a initialize ediliyo mu?

yamak

Hocam ayrı bi değişken tanımladım ben ama.Aşağıdaki gibi:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    int i;

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

Ben lineEdit'e i nin değerini yazdırdım.