调用方法时出现访问冲突异常

发布于 2024-08-21 14:19:36 字数 511 浏览 7 评论 0原文

我这里有一个奇怪的问题。假设我有一个带有一些虚拟方法的类。在某些情况下,此类的实例应该调用这些方法之一。大多数时候该阶段不会出现问题,但有时会发现无法调用虚方法,因为指向该方法的指针为NULL(如VS所示),因此出现内存访问冲突异常。怎么会发生这种事?

应用程序相当大且复杂,所以我真的不知道哪些低级步骤会导致这种情况。发布原始代码没有用。

UPD:好的,我发现我对问题的表述相当不确定,因此示意性代码看起来像

void MyClass::FirstMethod() const { /* Do stuff */ }
void MyClass::SecondMethod() const
{
    // This is where exception occurs, 
    // description of this method during runtime in VS looks like 0x000000
    FirstMethod(); 
}

不涉及构造函数或析构函数。

I've got a strange problem here. Assume that I have a class with some virtual methods. Under a certain circumstances an instance of this class should call one of those methods. Most of the time no problems occur on that stage, but sometimes it turns out that virtual method cannot be called, because the pointer to that method is NULL (as shown in VS), so memory access violation exception occurs. How could that happen?

Application is pretty large and complicated, so I don't really know what low-level steps lead to this situation. Posting raw code wouldn't be useful.

UPD: Ok, I see that my presentation of the problem is rather indefinite, so schematically code looks like

void MyClass::FirstMethod() const { /* Do stuff */ }
void MyClass::SecondMethod() const
{
    // This is where exception occurs, 
    // description of this method during runtime in VS looks like 0x000000
    FirstMethod(); 
}

No constructors or destructors involved.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

泪痕残 2024-08-28 14:19:36

堆损坏是一个可能的候选者。对象中的 v-table 指针很容易受到攻击,它通常是对象中的第一个字段。恰好与该对象相邻的某种其他对象的缓冲区溢出将擦除 v 表指针。对虚拟方法的调用通常会在很晚之后发生。

另一个典型的情况是有一个错误的“this”指针,通常为 NULL 或较低的值。当您调用该方法的对象引用错误时,就会发生这种情况。该方法将照常运行,但一旦尝试访问类成员就会崩溃。同样,堆损坏或使用已删除的指针也会导致这种情况。祝调试顺利;这绝非易事。

Heap corruption is a likely candidate. The v-table pointer in the object is vulnerable, it is usually the first field in the object. A buffer overflow for some kind of other object that happens to be adjacent to the object will wipe the v-table pointer. The call to a virtual method, often much later, will blow.

Another classic case is having a bad "this" pointer, usually NULL or a low value. That happens when the object reference on which you call the method is bad. The method will run as usual but blow up as soon as it tries to access a class member. Again, heap corruption or using a pointer that was deleted will cause this. Good luck debugging this; it is never easy.

吹泡泡o 2024-08-28 14:19:36

可能您正在从本身没有该函数的基类的构造函数调用该函数(直接或间接)。

可能某处存在损坏的强制转换(例如,当涉及多重继承时,指针的reinterpret_cast),并且您正在查看错误类的虚函数表。

可能(但不太可能)你已经以某种方式破坏了 vtable。

指向函数的指针是仅针对该对象为空,还是针对同一类型的所有其他对象?如果是前者,则 vtable 指针已损坏,并且您正在寻找错误的位置。如果是后者,则 vtable 本身已损坏。

Possibly you're calling the function (directly or indirectly) from a constructor of a base class which itself doesn't have that function.

Possibly there's a broken cast somewhere (such as a reinterpret_cast of a pointer when there's multiple inheritance involved) and you're looking at the vtable for the wrong class.

Possibly (but unlikely) you have somehow trashed the vtable.

Is the pointer to the function null just for this object, or for all other objects of the same type? If the former, then the vtable pointer is broken, and you're looking in the wrong place. If the latter, then the vtable itself is broken.

〆凄凉。 2024-08-28 14:19:36

可能发生这种情况的一种情况是,如果您尝试在析构函数或构造函数中调用纯虚方法。此时,该方法的虚拟表指针可能未初始化,从而导致崩溃。

One scenario this could happen in is if you tried to call a pure virtual method in a destructor or constructor. At this point the virtual table pointer for the method may not be initialized causing a crash.

烂柯人 2024-08-28 14:19:36

是否有可能在 SecondMethod 的处理过程中删除“this”指针?

另一种可能性是 SecondMethod 实际上是在前面使用无效指针调用的,并且它恰好在嵌套函数调用之前工作(通过未定义的行为),然后失败。如果您能够添加打印代码,请检查在执行这些方法期间的各个点上使用的“this”和/或其他指针是否类似于 0xcdcdcdcd 或 0xfdfdfdfd 。这些值(我相信)由 VS 在内存分配/释放上使用,这可能就是它在调试模式下编译时工作的原因。

Is it possible the "this" pointer is getting deleted during SecondMethod's processing?

Another possibility is that SecondMethod is actually being called with an invalid pointer right up front, and that it just happens to work (by undefined behavior) up to the nested function call which then fails. If you're able to add print code, check to see if "this" and/or other pointers being used is something like 0xcdcdcdcd or 0xfdfdfdfd at various points during execution of those methods. Those values are (I believe) used by VS on memory alloc/dealloc, which may be why it works when compiled in debug mode.

羁〃客ぐ 2024-08-28 14:19:36

您最有可能看到的是实际问题的副作用。最有可能的是堆或内存损坏,或者引用了以前释放的对象或空指针。

如果您可以始终让它在同一位置崩溃,并且可以找出从何处加载空指针,那么我建议使用调试器并在该内存位置的“写入”上放置一个断点,一旦断点被​​触发,那么很可能您正在查看实际导致损坏的代码。

What you are most likely seeing is a side-effect of the actual problem. Most likely heap or memory corruption, or referencing a previously freed object or null pointer.

If you can consistently have it crash at the same place and can figure out where the null pointer is being loaded from then I suggest using the debugger and put a breakpoint on 'write' at that memory location, once the breakpoint is trigerred then most likely you are viewing the code that has actually caused the corruption.

旧瑾黎汐 2024-08-28 14:19:36

如果仅当 Studio 无法显示方法地址时才发生内存访问冲突,则可能是由于缺少调试信息而导致。您可能正在调试使用发布(非调试)编译器/链接器标志编译的代码。

尝试在项目的 C++ 属性中启用一些调试信息,重建并重新启动调试器。如果有帮助的话,您将看到所有正常的可追踪内容,例如堆栈、变量等。

If memory access violation happens only when Studio fails to show method address, then it could be caused by missing debug information. You probably are debugging the code compiled with release (non-debug) compiler/linker flags.

Try to enable some debug info in C++ properties of project, rebuild and restart debugger. If it will help, you will see all normal traceable things like stack, variables etc.

水波映月 2024-08-28 14:19:36

如果您的 this 指针为 NULL,则不太可能发生损坏。除非你将内存归零,否则你不应该这样做。

您没有说您正在调试“调试”(未优化)还是“发布”(优化)构建。通常,在发布版本中,如果不需要,优化器会删除该指针。因此,如果您正在调试优化构建,将此指针视为 0 并不意味着任何事情。您必须依靠反汇编来告诉您发生了什么。如果您无法在调试版本中重现问题,请尝试在发布版本中关闭优化。调试优化构建时,您正在调试汇编而不是 C++。

如果您已经在调试未优化的构建,请确保在花费太多时间调试损坏的图像之前进行干净的重建。调试构建通常是增量链接的,并且已知增量链接器会产生此类问题。如果您使用干净构建运行调试构建,但仍然无法找出问题所在,请发布堆栈转储和更多代码。我确信我们可以帮助您解决这个问题。

If your this pointer is NULL, corruption is unlikely. Unless you're zeroing memory you shouldn't have.

You didn't say if you're debugging Debug (not optimized) or Release (optimized) build. Typically, in Release build optimizer will remove this pointer if it is not needed. So, if you're debugging optimized build, seeing this pointer as 0 doesn't mean anything. You have to rely on the deassembly to tell you what's going on. Try turning off optimization in your Release build if you cannot reproduce the problem in Debug build. When debugging optimized build, you're debugging assembly not C++.

If you're already debugging a non-optimized build, make sure you have a clean rebuild before spending too much time debugging corrupted images. Debug builds are typically linked incrementally and incremental linker are known to produce problems like this. If you're running Debug build with clean build and still couldn't figure out what went wrong, post the stack dump and more code. I'm sure we can help you figure it out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文