Two Bugs of VC++.NET2005 IDE

本文通过一个C++示例程序展示了多态性的实现方式,包括虚函数的使用及动态绑定过程。文中还探讨了VC++ .NET 2005环境中的一些显示问题,并提供了调试观察结果。

First let’s see a program

/*

Abstract    : A program to show polymophism.

Author      : Lijie Wang

Environment : Visual C++.NET 2005

History     : 2006-10-29

*/

#include<iostream>

using namespace std;

class B1

{

 public:

   virtual void vf1()

   {

        cout<<"B1::vf1"<<endl;      

   }

   virtual void vf2()

   {

        cout<<"B1::vf2"<<endl;

   }

   virtual void vf3()

   {

        cout<<"B1::vf3"<<endl;    

   }

   void B1f(){}

};

 

class B2

{

 public:

   virtual void vf2()

   {

        cout<<"B2::vf2"<<endl;      

   }  

   virtual void vf3() 

   {

        cout<<"B2::vf3"<<endl;     

   }

   virtual void vf4()

   {

        cout<<"B2::vf4"<<endl;

   }

   void B2f(){}

};

 

class D : public B1, public B2

{

public: 

   void vf1()  //overide B1::vf1 and B2::vf1

   {

        cout<<"D::vf1"<<endl;     

   } 

   void vf3()

   {

        cout<<"D::vf3"<<endl;     

   }   

   virtual void vf5()   //additional virtual function

   {

        cout<<"D::vf5"<<endl;

   }

   void Df()  //non virtual function

   {

        cout<<"D::Df"<<endl;

   }

   void Set_A(int n)

   {

        a = n;

        cout<<"D::A="<<a<<endl;

   }

private:

     int a;

};

 

void main()

{

     D d;

     B1 b1;

     B2 b2;

     B1 *pb1 = &d; //pb1 point to the B1-sub-object of D

     B2 *pb2 = &d; //pb1 point to the B2-sub-object of D

 

     d.vf3();

     d.vf5();

     b1.vf1();

     b2.vf3();

 

     pb1->vf1(); //danymic binding

     pb1->vf2(); //danymic binding

     pb1->vf3();

     dynamic_cast<D*>(pb1)->Set_A(1);

 

     pb2->vf2();

     pb2->vf3();

     pb2->vf4();

     dynamic_cast<D*>(pb1)->vf5();

}

The class diagram of this program is shown in Fig 1.

Fig 1. Class Diagram

The structure of d object can be found from the Watch Window while debugging, just like Fig 2:

Fig 2. Structure of d Object

We can find from the structure of the d object that it includes a B1 sub-object and a B2 sub-object with a __vfptr in each one. From the vftables we can see that D::vf1 has overridden the B1::vf3 and B2::vf3, just according to our expectation. But we can not find the new virtual function D::vf5 in the vftables. There are only two __vfptrs in the d object and each belongs to a sub-object. But we know, to support polymorphism the D::vf5 should be in the __vfptr of d object. The only way to satisfy the need is to insert D::vf5 into one of the two __vfptrs of the sub-objects, but we find none.

Let’s see the address of d.vf5 from the Watch Window:

Fig 3. Address of d.vf5

This indicates that the address of d.vf5 is 0x00411208.

Then we can find the address of the vftable of B1 sub-object or say d.B1.__vfptr from the Watch Window:

Fig 4. Address of d.B1.__vfptr

So the address of the B1.__vfptr of d is 0x00417744, then we turn to the Memory Window to check what is stored in the vftable of B1 sub-object:

Fig 5. Memory content from of vftable of B1 sub object of d

From the picture above we can see that the four successive words stored in the vftable of B1 sub-object are: 0x004111e5, 0x00411091, 0x004111bd, 0x00411208. 0x00411208 is just the address of d.vf5, this indicates that d.vf5 is actually inserted in the end of the first sub-object vftable of d, here is vftable of B1 sub-object. But we can not find it from Fig 2. So I think this is a bug of the VC++.NET IDE (I use VC++.NET 2005).

Then the we modify the program by replacing each vf* function by f*. Then the structure of the d object in the Watch Window is shown in the Fig 6.

Fig 6. Structure of d Object After Modification

From the Fig 6 we find D::vf1, B1::vf2 and D::vf3 in the vftable of B1 sub-object, which is obviously not right.  But if you create a new project and copy the program, the displayed structure of d will be all right. I think this is also a bug of VC++.NET IDE.

 

 
### 关于MIPS编译器中的Segmentation Fault错误 当在MIPS架构下使用GCC编译C++程序时,如果遇到`cc1plus segmentation fault`或类似的内部编译器错误(Internal Compiler Error, ICE),这通常表明编译器本身遇到了不可预期的情况并崩溃了。此类问题可能由多种原因引起,包括但不限于: #### 编译器版本兼容性 某些特定版本的GCC可能存在已知的缺陷,在处理复杂模板元编程或其他高级特性时容易触发segmentation fault[^1]。因此建议尝试升级到更新版本的GCC以解决潜在的bug。 #### 输入源码问题 复杂的代码结构或者不标准的语言扩展也可能引发ICE。例如过度嵌套的模板实例化可能导致栈溢出从而造成分段错误[^2]。 ```cpp template<int N> struct Factorial { enum { value = N * Factorial<N - 1>::value }; }; template<> struct Factorial<0> { enum { value = 1 }; }; // 如果N过大可能会导致递归过深而失败 int main() { return Factorial<8000>::value; } ``` 上述例子展示了极端情况下模板递归定义如何影响编译过程稳定性[^3]。 #### 环境配置不当 交叉编译环境中目标平台与主机平台差异较大时也易发生异常行为。确认工具链设置无误非常重要,比如指定正确的三元组(triplet),以及匹配的目标体系结构选项如 `-march=mips32` 或者 `-mtune=74kc` 等参数设定是否恰当[^4]。 对于具体解决方案可以考虑以下几个方面来排查和修复该类问题: - **更新/更换编译器**: 使用最新稳定版GCC往往能规避很多旧版本中存在的bugs。 - **简化测试案例**: 将原始项目逐步精简直至找到最小可重现此现象的例子,便于定位根本原因。 - **启用调试标志**: 添加更多诊断开关如 `--save-temps`, `-v`, 和 `-fdiagnostics-show-location=once` 来获取额外信息辅助分析。 - **报告给开发者社区**: 当确定这是一个新的未记录过的issue之后,可以通过官方渠道提交Bug Report帮助改进软件质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值