GTKMM的内存管理

  ——读 GTKMM Tutorial 笔记。
    by Yazy, 2005-6-4


1、传统 C++ 内存管理方式
   1. 类作作用域内的构件
     将构件声明为类的成员变量,不使用动态内存分配机制。使用这种方式的优点是“memory
     management is grouped in one place.”,随着类的创建与销毁,构件也随之存在与消失。

     // From the tutorial:
     #include <gtkmm/button.h>
     class Foo
     {
     private:
       Gtk::Button theButton;
       // will be destroyed when the Foo object is destroyed
     };

     我用这种方式使用构件时出现问题。我从 Gtk::Window 继承类 HelloWorld,并在HelloWorld
     里声明两个或者两个以上的构件,比如 Gtk::Button 时,编绎出来的程序会 crash。折腾了好
     久,未有的确结论。现在只猜测是堆栈益出(要求过多堆栈空间,系统未能满足),因为从main
     的第一行开始,我所有的对象都是在堆栈里的,main 内容大致如下:

     int main(...) {
       Gtk::Main kit(argc, argv);
       HelloWorld hello;
       kit.run(hello);
       return 0;
     }

     程序运行时上面 hello 将存在于堆栈中,其成员(复合型)也当然如此。若 HelloWorld 有
     m_button1 及 m_button2 两个成员,那它们也都存在于堆栈之中,所以我猜想我的程序
     crashed 于堆栈益出。但是……一个 Gtk::Button 对象会很大吗?或者说两个构件就足以用光整
     个堆栈吗?想到那几成员构件的大小,我对自己这样的猜测感到怀疑。我可以确认我的程序运行
     之时内存还没达到“高危”境况。

     同样的因堆栈要求过大而导致程序崩溃的情况我以前在 MFC 环境也遇到过。当我在一个函数作
     用域内一下子要求 2048 Bytes 作为缓冲时,程序便垮了。直至我减小要求的缓冲大小,情况才
     正常。

     此次的开发平台与当时不一样,现在我用的是 MinGW 的 GCC(3.4.2),不知道编绎平台的不
     同会不会影响程序堆栈大小的不同。

     当我将 HelloWorld 的几个构件成员都换成堆对象(并将对象交由 GTKMM 托管,即下文出现的
     内容)时,程序便不再烦人了。

   2. 函数作用域内的构件
     即在函数体内使用堆栈构件。这种方式的优点是“the increased data hiding and reduced
     dependencies(提高了数据隐藏、减少了依赖性)”。同样,如果堆栈大小有限,那这种方式
     同样也会使用程序崩溃。

   3. 使用 new 和 delete 动态分配
     使用堆对象,要求程序员手动地配对使用 new 和 delete,不然便会造成 Memory Leak。堆一
     般认为是不会不够用的,使用它的麻烦在于 new 和 delete 配对的麻烦,容易造成失误。

2、托管构件
   托管构件是使用 new 创建的堆构件,但对构件的内存回收都交给 GTKMM 来完成(准确地说是容器
   构件),所以程序员不必调用 delete,不必担心配对问题。容器在自身销毁之时会销毁其管理之下的
   子构件。

   // From the tutorial:
   MyWidget::MyWidget()
   {
     Gtk::Button* pButton = manage(new Gtk::Button("Test"));
     add(*pButton); //add aButton to MyWidget
   }

   上面的 manage 是容器的方法,GTKMM的所有构件都有 set_manage 方法,可以将自己委托于父
   构件:

   // From the tutorial:
   foo.add( (w=new Gtk::Label("Hello"), w->set_manage(), &w) );
   // is the same as the following, but more tedious
   foo.add( manage(new Gtk::Label("Hello")) );

   Top Level 容器不能成为其它容器的子构件,所以这类容器不能委托于“人”,如果使用将它们放于
   堆中,我们必须考虑上面的问题。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值