C++ Space

C++, 3DGame

2007年4月20日 #

关于DLL中对象的动态创建与删除的问题

最近有看到一些文章讨论怎样轻松的使用DLL,其中有一个错误,那就是在DLL中创建的对象未在DLL中删除,如下示:

//someheadfile.h
#include<memory>

class __declspec(dllexport) Interface
{
 
public:
  virtual 
void foo() = 0;
}
;

class __declspec(dllexport) Impl : public Interface
{
 
public:
   virtual 
void foo()
   
{}
}
;

__declspec(dllexport)
std::auto_ptr
<Impl> DLLCreate()
{
  
return std::auto_ptr<Impl>(new Impl);
}

上面的做法貌似可以做到自动删除动态生成的对象,但,只有DLL和用户都动态链接C/C++运行库时它才会运行正确,否则,创建和删除会在不同的堆栈空间进行,从而导致错误 
所以还是老实的在提供一个
DLLDelete()用于删除在DLL中生成的对象。

posted @ 2007-04-20 13:35 Kooyu 阅读(1476) | 评论 (6)编辑 收藏

2007年4月3日 #

一个浮点数表示产生的问题

半夜里刚睡着又被电话叫醒,一个项目的现场数据出现了错误。
我们的程序要分析的报告里的某一个字段使用了定点小数的表示方法,即两个字节表示整数部分,再两个字节表示小数部分。刚开始的时候没注意到这里有个问题,那就是这种表示法要求小数部分一定是定长的,否则,就无法解析。例如,0.03和0.30的表示不同在哪里,0.30可不可以表示成0.300。怪我当初考虑欠佳,失败。

posted @ 2007-04-03 00:27 Kooyu 阅读(948) | 评论 (0)编辑 收藏

2007年3月9日 #

ACE_CDR::mb_align(ACE_Message_Block * mb)使用问题

ACE_CDR::mb_align(ACE_Message_Block * mb)用于对齐mb内部数据块ACE_Data_Block所拥有的内存的起始地址,它的实现大致如下:

void
ACE_CDR::mb_align (ACE_Message_Block 
* mb)
{
  char 
*   const  start  =  ACE_ptr_align_binary(mb -> base (),   ACE_CDR::MAX_ALIGNMENT);

  mb
-> rd_ptr (start);
  mb
-> wr_ptr (start);
}

由于要执行内存地址对齐,那么mb->base()所指示的地址可能需要向后移动(MAX_ALIGMENT - mb->base() % MAX_ALIGMENT)个字节。但在这个之后,mb->base()指向的可用内存将比它自己薄记的少,如果需要程序正常运行,那么依赖于在往它写入数据时,写入的字节数不能大于实际大小(这个实际大小为 :mb的薄记大小-移动的距离),而这需要由程序员来控制,容易出错也就难免了。

也许可以在函数mb_align内部重设mb的大小,使其薄记大小与实际有效内存大小相符,但这引起内存拷贝,这个代价也太大了。

内存对齐的处理似乎应该在内存分配阶段,比如提供类似下面的分配已对齐地址功能的分配器:

struct Align_Alloc
{
    void 
*  align_alloc(size_t size, unsigned align)
    {
        void 
*  ptr  =   new  char[size  +  align];
        return align_mb_ptr(ptr, align);
    }
};

但ACE实际上没这么做,它提供mb_align这个与内存分配毫不相干的功能,且希望由程序员自己来解决可能引发的问题!~
 

posted @ 2007-03-09 15:33 Kooyu 阅读(1577) | 评论 (0)编辑 收藏

2007年3月7日 #

"危险"的函数指针类型的强制转换

查看一个与别人合作的项目的代码,发现了一个“隐秘”的问题,模拟这个问题如下:

typedef void ( * foo_type)( int int );

void foo1(
int int )
{
}

void foo2()
{
}

int  main()
{
  foo_type f 1
=   & foo1;                      // <1>
  foo_type f 2
=  (foo_type) & foo2;   // <2>
     return 0;
}
语句<1>肯定是对的,语句<2>强转一个函数类型到foo_type类型,我当时担心这会不会导致下面的语句导致运行时错误:
(*f2)(1,2);

幸运时这里它不会导致错误,这是由于:
<1>我们使用C/C++的默认函数调用方式__cdecl,也就是传入的函数参数是由调用者清理的;
<2>函数foo2没有使用任何参数。
这种做法肯定不值得提倡,但实际的项目中要避免还是不太容易,毕竟每个人的习惯不一样,还有为了与框架协同工作,有时候可能也不得不这样做。但是,一旦函数调用方式发生改变,或者被强转的那个函数是带参数的,而它又使用了这些参数,隐秘的错误也就埋下了。

posted @ 2007-03-07 13:38 Kooyu 阅读(3010) | 评论 (1)编辑 收藏

2007年3月6日 #

实在让人无法忍受

C++ = VC++ = MFC/ATL/COM
我已经记不清多少次看到与此类似甚至比这更离谱的关于C++的表述,真是害人不浅,特别是对C++新手而言。
还有一些C++的半调子动辄批评、讽刺他们一知半解的C++特性,拿C++与另一种毫不相干的语言大肆比较,得出稀奇古怪的结论。

一些气话,心情不好。

posted @ 2007-03-06 13:17 Kooyu 阅读(2211) | 评论 (7)编辑 收藏

仅列出标题