运行时原因可能是什么?无法找到虚拟表的链接符号..." Qt中的错误?

时间:2016-02-03 07:51:54

标签: c++ qt linker vtable

此问题以类似方式多次提出,例如stackoverflowforum.qt.ioqtcentre.org。问题是此错误消息非常模糊,以至于一个解决方案无法应用于另一个方案。大多数线程在讨论过程中已经死了: - (

因此,我在Qt应用程序中收到的完整错误消息是:

找不到虚拟表的链接符号,用于" OneOfMyClasses"
值 找到" QString :: shared_null"代替

OneOfMyClasses 根据各种不同而变化, QString :: shared_null 对于我得到的所有错误保持不变。以下是我的日志记录控制台的屏幕截图:

enter image description here

  1. 为什么字体颜色为粉红色,那么谁正在打印此邮件?
  2. 为什么我在设置断点并单步执行代码时才会看到此消息?简单地运行应用程序时不会出现此消息。
  3. 它发生的地方是在当前位置之前的源线中的此函数(黄色箭头):

    enter image description here

    因此根据消息我进入m_pStateWidget->insertNavLabel(...)并且错误消息被打印在Qt内与QString类相关的构造函数中的某处。所以我尝试了以下方法,将问题从这个代码位置移开:

    enter image description here

    执行此操作时,我会在消息中使用另一个类名获得相同的错误消息,但请注意 QString :: shared_null 保持不变。

    在我看来,我有某种腐败的记忆。

    1. 我应该如何开始调查此问题?我害怕更改代码,因为这可能会隐藏上述问题。
    2. QString :: shared_null的用途是什么?我发现其他人经常在错误消息中看到相同的内容。
    3. 感谢您的任何提示或帮助! : - )

      编辑:它现在变得非常有趣。我已经在打印消息之前插入了每个函数,最后我得到了这些错误消息:

      enter image description here

      在这个位置:

      enter image description here

      当我在QtCreator中浏览调用堆栈时,每次在堆栈中选择另一个函数时,都会反复打印错误。

      1. 这是否意味着调试器正在打印消息,而且为我解决某些类型的东西真是太愚蠢了,或者这是否意味着我遇到了严重的麻烦?

2 个答案:

答案 0 :(得分:1)

<强>原因: 在代码中的某处,您可能会超出实际内存

示例1:

int elmArray[10];
for(int i = 0; i < 20; ++i)
{
elmArray[i] = 0;
}

在上面的例子中,实际数组大小为10,但我们将索引的值分配给10以上。

示例2:

char* cpyString;

strcpy(cpyString , "TEST");

这些场景最终可能会将值写入其他对象。大多数情况下可能会损坏虚拟表。这会给出上述警告。

<强>修正: 如您所知,只需更正下面的代码即可。 示例:

int elmArray[10];
for(int i = 0; i < 10; ++i)
{
elmArray[i] = 0;
}

char cpyString[10];
strcpy(cpyString , "TEST");

在您的情况下似乎是,您正在将QTString :: shared_null分配给某些未初始化的字符串。

答案 1 :(得分:1)

在不同的网站上讨论了“无法找到虚拟表的链接器符号...”问题的各种线程。尽管给出了一些特定示例的解决方案,但很少有人解释为什么会出现此问题。遇到困难之后,我想分享一下我学到的东西。

首先,此错误消息仅在Linux构建中出现,而在Windows构建中未出现。嗯.....

在我的情况下,问题是由同一线程再次调用非重入方法引起的。一旦发现问题,就可以通过使用静态的忙碌标志来修复,并且只需在第二次调用忙碌时返回即可。简而言之,这就是问题和解决方案。但是我是怎么陷入困境的呢?

那么非租户方法实际上是一个Qt插槽。因为我知道有可能从第一个调用第二个调用(实际上是发出),所以使用Qt :: QueuedConnection建立了连接。但是,稍后我在处理函数时设置了一个初始屏幕QSplashScreen。我几乎没有意识到名为QApplication :: processEvents()的QSplashScreen :: repaint()调度了第二个违规发射。

因此,我可以通过删除QSplashScreen并使用QLabel来解决此问题。但是,尽管两者都可以在Windows上很好地工作,但实际上都不能在Linux上工作,但是它们建立了一个半透明的窗口并且不绘制内容(即使repaint()和processEvents()也不执行)。因此,这可能是Qt Linux错误,这是另一回事了。

也许这应该张贴在其他地方,如果可以,对不起.....