【问题标题】:What is causing my first-chance (stack overflow) exception in Qt?是什么导致我在 Qt 中的第一次机会(堆栈溢出)异常?
【发布时间】:2016-01-04 09:20:14
【问题描述】:

我有一个应该在 CurrentTextChanged 上更新的 QComboBox。我创建了以下连接语句,以便 QComboBox 触发 onFilterComboBoxCurrentTextChanged 插槽:

connect(m_viewController->getFilterWindow()->getFilterComboBox(), &QComboBox::currentTextChanged, this, &MainController::onFilterComboBoxCurrentTextChanged);

clearAndAddDICOMTagsToShownTagsListWidget 会导致以下错误。我该如何解决这个问题?

void MainController::onFilterComboBoxCurrentTextChanged(QString filterName)
{
    m_viewController->clearAndAddFilterNamesToFilterComboBox(m_fileController->loadFilterNamesFromConfigFile());
}

QStringList FileController::loadFilterNamesFromConfigFile()
{
    QSettings settings(QDir::toNativeSeparators("C:\\HelloWorld\\Config\\Filter.cfg"), QSettings::IniFormat);
    QStringList filtersNames = settings.childGroups();
    return filtersNames;
}

    void ViewController::clearAndAddFilterNamesToFilterComboBox(QStringList filterNames)
{
    m_filterWindow.getFilterComboBox()->clear();
    m_filterWindow.getFilterComboBox()->addItems(filterNames);
}

QListWidget* FilterWindow::getShownTagsListWidget()
{
    return ui.shownTagsListWidget;
}

DoseView.exe 中 0x777EAFC0 (ntdll.dll) 处的第一次机会异常: 0xC00000FD:堆栈溢出(参数:0x00000001、0x002C2FFC)。

DoseView.exe 中 0x777EAFC0 (ntdll.dll) 处的未处理异常: 0xC00000FD:堆栈溢出(参数:0x00000001、0x002C2FFC)。

【问题讨论】:

  • 我们需要查看clearAndAddFilterNamesToFilterComboBox 方法。最有可能的是,您导致在函数内部发出 currentTextChanged 信号,从而导致对插槽的递归调用,从而导致堆栈溢出。
  • @Jaa-c 抱歉,我在问题中粘贴了错误的函数:)。我已经更新了代码
  • @Jaa-c 我该如何解决这个问题?不幸的是,我不完全理解为什么它会导致递归调用 -> 堆栈溢出
  • @Engo 发生这种情况是因为onFilterComboBoxCurrentTextChanged 调用clearAndAddFilterNamesToFilterComboBox,这会更改组合框中的文本,从而导致调用onFilterComboBoxCurrentTextChanged,等等。为什么每次更改组合框时都要重新填充它?
  • @molbdnilo 感谢您的精彩解释!

标签: c++ qt exception stack-overflow


【解决方案1】:

递归看起来像这样:

  1. 组合框中的文本更改
  2. 您调用 clear(它会导致文本更改)
  3. 返回 1 - 准备好递归。

如果您在对组合框对象执行操作时需要停止信号传播,请调用 blockSignals。但是,我真的会重新考虑您的应用程序逻辑。我经常使用 Qt,并且不需要经常使用 blockSignals。

【讨论】:

  • 你对“重新思考你的应用逻辑”是正确的。我已经重构了我的代码,我不需要任何块信号 :)
【解决方案2】:

简单的解决方法是在更新组合框的项目之前阻止信号。像这样:

void MainController::onFilterComboBoxCurrentTextChanged(QString filterName) {
combobox->blockSignals(true); 
m_viewController->clearAndAddFilterNamesToFilterComboBox(m_fileController->loadFilterNamesFromConfigFile());
combobox->blockSignals(false);
}

但我相信您应该能够通过更好地设计代码来防止它发生。

【讨论】:

  • 你说的“更好的设计”是对的。我已经重构了我的代码,我不需要任何块信号 :)
猜你喜欢
  • 2011-01-13
  • 1970-01-01
  • 2010-09-11
  • 2016-02-24
  • 2010-10-02
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 2018-07-01
相关资源
最近更新 更多