这几天不知道怎么回事,本来好好的程序,突然跑不起来了,调试发现是CreateWindowEx函数里面出的问题,pParentWnd=NULL,无法创建窗口。本来以为程序那块出了问题,查了半天,调试半天不能解决问题。怀疑可能是用的ActiveX可能出问题了,重装也不管用。
于是怀疑到是不是编译器的dll出了问题,重装了VC6,解决。
同时遇到的问题有,一个线程关闭的时候调试错误,出现异常,调试发现是在"scalar deleting destructor"中,调用delete出现的。查询scalar deleting destructor发现如下内容:
http://www.pediy.com/bbshtml/bbs8/pediy8-778-2.htm
当类有虚析构函数时,编译器生成一个辅助函数来删除它。其目的是当析构一个类时确保_delete_操作符被调用。删除析构函数的伪码如下:
virtual void * A::'scalar deleting destructor'(uint flags)
{
this->~A();
if (flags&1) A::operator delete(this);
};
这个函数的地址被放入vftable替换析构函数地址。通过这种方式,如果另外一个类覆盖了这个虚析构函数,那么它的_delete_将被调用。然而实际代码中_delete_几乎不会被覆盖,所以你通常只看到调用默认的delete()。有时候,编译器也生成一个删除析构函数向量,就像下面一样:
virtual void * A::'vector deleting destructor'(uint flags)
{
if (flags&2) //destructing a vector
{
array = ((int*)this)-1; //array size is stored just before the this pointer
count = array[0];
'eh vector destructor iterator'(this,sizeof(A),count,A::~A);
if (flags&1) A::operator delete(array);
}
else {
this->~A();
if (flags&1) A::operator delete(this);
}
};
我跳过了有虚基类的类的大部分实现细节,因为它们使得事情更复杂了,而且在现实生活中很少用到。请参考Jan Gray写的文章[1]。它已经很详尽了,只是用匈牙利命名法有点头痛。文章[2]描述了一个MSVC实现虚继承的实现。更多细节还可以看MS专利[3]。
程序中经过确认确实没有问题,重装VC后确实解决了。看来dll出错时,编译器的堆栈还是不能尽信的。