今天遇到一个Access Violation的crash,只看crash call stack没有找到更多的线索,于是在debug模式下又跑了一遍,遇到了如下的一个debug的错误提示框:

这个是什么原因呢?我们来看一个简单的例子来重现这个错误。

假设我们有2个父类,分别是BaseA和BaseB。有一个子类Child,继承自BaseA和BaseB。

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class BaseA
{
public:
virtual void foo()=0;
}; class BaseB
{
public:
virtual void bar(int a)=0;
}; class Child: public BaseA, public BaseB
{
public:
void foo()
{
cout<<"i'm foo in Child!"<<endl;
};
void bar(int a)
{
cout<<"i'm bar in Child!"<<endl;
};
};

 

假设我们有如下的main函数:

 1
2
3
4
5
6
7
8
9
10
int main() {

    BaseB* b = new Child();
BaseA* a = (BaseA*)b;
BaseA* a2 = dynamic_cast<BaseA*> (b);
// This is actually calling bar(),
// and will cause Runtime check failure about ESP if the foo and bar have different signature.
a->foo();
a2->foo();
}

 

在这个main函数里a是通过C-Style的强转转来的,a2是通过dynamic_cast转换来的。如果我们运行这个程序,在release下就会报access violation的crash,在debug下就会出上面列的ESP错误的对话框。

函数的输出如下图所示:

这就能解释为什么会出这个ESP的错误了,因为我们想调用foo,但是实际上调用的bar,但是foo和bar的函数签名不一样,所以导致了出现那个debug版本下的ESP的错误提示。但是加入我们把bar(int a)中的参数去掉,这样foo和bar就有一样的函数签名了,这样及时在debug版本下也不会出这个ESP的提示,在release或者debug模式下都不会报任何错误,但是我们在runtime调用了错误的函数!!!

可以看看下图回忆一下vtable是怎么回事:)

 

也可以参考怎么看C++对象的内存结构 和 怎么解密C++的name mangling - fresky - 博客园来看看C++对象的内存结构。

对于ESP的错误,可以参考stackoverflow上的这个问题:c++ - Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call - Stack Overflow

C++程序在debug模式下遇到Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call问题。的更多相关文章

  1. VS2015创建的C++程序在Debug模式下不能调试

    如题,不能调试的问题,解决办法: 1.修改工程属性页 2.修改VS2015托管兼容模式 工具->选项->调试,勾选使用托管兼容

  2. 引入 Tinker 之后如何在 Debug 模式下开启 Instant Run

    在<Tinker + Bugly + Jenkins 爬坑之路>一文中讲了在接入 Tinker 之后,Jenkins 中的一些坑,由此,热修复算告一段落,但是,在直接 Run 模式运行时, ...

  3. Debug模式下加载文件,运行程序异常的慢

    今天在进行单元测试的时候,debug模式下加载速度很慢,但是run模式下速度很快. 原因:在debug模式下,断点位置不当,解决办法 移除编译器中的所有断点.

  4. Myeclipse在debug模式下没加断点程序卡住,start模式下可以正常启动

    参考<eclipse在debug模式下卡住,start模式下可以启动>,地址:https://blog.csdn.net/jack_chen1994/article/details/761 ...

  5. Intellij IDEA debug模式下项目启动慢/无法启动的事件解决过程记录

    项目无法启动了 简单的介绍一下事件过程:周一的早上,收到前端同事抛过来的一个任务,说是一个接口无法正常返回数据,于是就让他把参数发过来,我想试着在本地重现一下并且将问题修复掉,这种情况肯定是要通过de ...

  6. Debug模式下编译溢出问题

    问题: 代码在Debug模式下编译报出内存溢出的错误,而Release模式下则没有. 由于Debug模式下包含调试信息,并且不作任何优化.而Release模式进行了各种优化,内存检测等操作均省去,使得 ...

  7. Debug模式下,测试app后缀名“-测试”

    target-->buildsetting-->user-defined 新建一个和上图尖括号一样的字符 如下图: 在debug中填入后缀名,然后在debug模式下运行程序,会发现debu ...

  8. 在debug模式下引入一些性能检测工具

    我们经常在debug模式下使用一些性能检测工具,例如blockCannary,leakCannary.Stetho等,但是我们release的时候又不需要这些检测工具,通常情况下我们的做法是在buil ...

  9. IDEA Debug模式下启动慢的解决办法

    工程没有做什么大的改动,近期Idea在debug模式下启动耗时800s +,run模式下200s.Idea debug模式启动的时候会有这样的提示: 方法断点会戏剧性的降低debug的速度.当时并没有 ...

随机推荐

  1. Shell脚本——中继DHCP服务器自动部署

    详细说明参照: (四)跟我一起玩Linux网络服务:DHCP服务配置之中继代理 vm1的脚本是: #! /bin/bash HIPSEG="10.10.10" SIPSEG=&qu ...

  2. 浅谈ListBox控件,将对象封装在listBox中,在ListBox中显示对象中某个属性,在ListBox中移除和移动信息

    大家好,俗称万事开头难,不经历风雨,怎能见彩虹.在此小编给大家带来一个自己练习的小实例,希望与大家一起分享与交流.下面进入应用场景,从SQL2008数据库取出数据,给ListBox赋值在界面并显示出来 ...

  3. Listview控件实现已选择效果

    Winform中用Listview控件实现更新点击选择后已选择效果,如图: 代码如下: private void frmSelect_Load(object sender, EventArgs e) ...

  4. thinkphp3.2 namespace及use用法

    PHP 5.3中的namespace其实是个不错的东西,可以简化编程,下面介绍三类在代码中 访问namespace中类的方法 1 引用namespace和类   假设namespace的程序为name ...

  5. 学习Swift -- 析构过程

    析构过程 析构器只适用于类类型,当一个类的实例被释放之前,析构器会被立即调用.析构器用关键字deinit来标示,类似于构造器要用init来标示. 原理 Swift 会自动释放不再需要的实例以释放资源, ...

  6. 移除Sourcesafe与VC6的绑定

    整理日: 2015年2月16日 HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Source Control\Disabled

  7. 我的iphone6退货之路

    开篇 匆匆这一年又快结束了,眼看年关将近,老婆的生日也快到了,正打算给老婆买个礼物,由于现在老婆用的手机是公司的工程机,而且还是低端产品,所以一直想给老婆改善改善,也算是对老婆这一年来辛苦的默默的支持 ...

  8. iPhone开发 - 常用库

    iPhone开发 - 常用库 这里总结了iPhone开发者开发过程中可能需要的一些资源 如何用Facebook graphic api上传视频: http://developers.facebook. ...

  9. 上网必备AdBlock,远离广告!

    浏览器广告拦截插件,绝对上网必备... 从此告别讨厌的百度边栏广告!!! https://getadblock.com/ https://adblockplus.org/zh_CN/

  10. MacOS快捷键