C++ 未调用的函数必须存在,否则代码会爆炸

C++ Function that is not being called has to be present or code explodes

本文关键字:代码 存在 调用 函数 C++      更新时间:2023-10-16

所以我有一个非常奇怪的问题,如果我的代码中不存在这个函数,它将无法工作。它可以是任何名字,它必须存在。我甚至在代码中有一个 exit(EXIT_FALURE) 语句,如果存在,它将运行。(请注意,这是在多台计算机上发生的(。

基本上,我必须有如下所示的代码:

void dosomething()
{
  Camera dummyCamera;
  dummyCamera.refreshTransform(0,0);
}

但是我可以像这样重命名函数,它仍然有效

void thisStillWorks()
{
  Camera dummyCamera;
  dummyCamera.refreshTransform(0,0);
}

无需更改代码中的其他任何内容。从不显式调用此函数。但是,如果我注释掉方法主体,则可以在运行时注意到差异。

这是这个奇怪事情的视频...

http://youtu.be/PIyGOoMAa6Y

不起作用的解决方案:- 干净的数据
- 注释掉代码
- 在代码库中
查找 #define- 删除派生数据
- 在函数体中设置断点(只是跳过

(

如果你真的很好奇,你可以在这里克隆我们的仓库(你需要自己安装依赖项(:

https://github.com/fnk0/MarcusGameEngine

我的一些猜测。

  • 我最好的猜测是内存损坏,并且完全巧合地用这个函数指针覆盖了 vtable 值。或者进行了某种无效的跳转,由于不同的指令填充,它变得可见。要进行调查,请使用valgrind。

  • 如果不是这种情况,我想你的编译器/链接器有点坏了。尝试从头开始重新编译所有内容(通过删除所有 .o 文件(。

  • 我可以想象这样一种场景:您的库动态链接,并且您通过索引或其他东西调用动态加载的方法。

  • 你做到了:

    #define void void myDefaultFunctionNameIamATroll() //
    

这很有可能是由内存损坏引起的。瓦尔格林德会在这里帮助你。在调试/发布模式和编译器优化级别之间更改行为是检查这一点的另一种方法。

基本上,根据代码在内存中的加载方式,不同的位置可能会被无效的指针访问覆盖,因此为函数定义主体将更改布局并防止硬崩溃。

您的refreshTransform函数是隐式inline,因为它是在class体内定义的。

这意味着如果有两个不同的编译单元定义了void Camera::refreshTransform(float, float)的实现,那么除了一个之外,其他所有单元都将被静默丢弃。 如果实现不同,则程序格式不正确,不需要诊断。

简而言之,由于包含顺序头文件、预处理器符号、在该函数中调用的函数的公开重写,或者递归应用于每个inlinetemplate以及从该函数调用的类内方法和函数的相同错误,某些代码有两种不同的实现。

当您在该特定编译单元中调用它时,某些inline函数被标记为已使用,并且"丢弃除一个之外的所有"最终会选择另一个。

现在,这也可能是其他一些定义规则违规 - 某些类型的大小在不同的编译单元中不同,某些变量或常量的值等。

若要解决此问题,可以停止inline方法。 您可以将inline函数和template函数保留在匿名命名空间中。 您可以跟踪相关函数在更改和不更改时的行为方式。 并递归搜索。