今天遇到一个Access Violation的crash,只看crash call stack没有找到更多的线索,于是在debug模式下又跑了一遍,遇到了如下的一个debug的错误提示框:
这个是什么原因呢?我们来看一个简单的例子来重现这个错误。
假设我们有2个父类,分别是BaseA和BaseB。有一个子类Child,继承自BaseA和BaseB。
1 |
class BaseA |
假设我们有如下的main函数:
1 |
int main() { BaseB* b = new Child(); |
在这个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的错误,可以参考*上的这个问题:c++ - Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call - Stack Overflow