无法调试segfault,涉及connect()

时间:2015-04-26 14:37:29

标签: c++ segmentation-fault qt4

嗨:)我正在尝试为自制的RPG创建一个角色表生成器:)我在调试一个奇怪的段错误时遇到了一些麻烦。

究竟发生了什么:

  1. 我在_c CCharacter对象中初始化_skills,然后第一次调用updateSkillBoxes()。它完美无缺。
  2. 我可以在我的_skills中添加其他CUSkill,再次调用updateSkillBoxes(),添加它们没有问题
  3. 如果我使用QComboBox名称更改一个技能的名称,它会调用onSkillChanged(),结束该功能而不会崩溃(我看到“onSkillChanged()已完成”qDebug()消息),然后在app.exec中崩溃()在我的main.cpp
  4. 我尝试了什么:

    1. 直接调用我的connect上的updateSkillBoxes()(稍微更改了代码以更新里面的数据):同样的问题。
    2. 将连接置于CSkillInput初始化或onSkillChanged中,同样的错误
    3. 删除updateSkillBoxes()中的connect,并将onSkillChanged()连接到UI中的按钮。它工作得很好,所以功能似乎有效(连接部分除外)
    4. 以下是代码:

      void CGenerator::updateSkillBoxes()
      {
          qDebug() << "updateSkillBoxes() started";
          //First we remove
          int skillNum=_skillI.size();
          for(int i=0;i<skillNum;i++)
          {
              delete(_skillI.takeAt(0));
              delete(_skillInputLayout.takeAt(0));
              delete(_skillInputBox.takeAt(0));
          }
      
          //Clean skillGrid
          QLayoutItem *child;
          while ((child = _skillGrid->takeAt(0)) != 0)
          {
              delete child->widget();
              delete child;
          }
          delete _skillGrid;
      
          _skillGrid = new QGridLayout;
          for(int i=0;i<_c->getSkill().size();i++)
          {
              CUSkill *skill = _c->getSkill()[i];
              QPointer<QGridLayout> tmpLayout = new QGridLayout;
              QPointer<QGroupBox> tmpBox = new QGroupBox;
              //Recreate new input
              QPointer<CSkillInput> tmpInput = new CSkillInput(d->getSkillNameList(), d->getSkillIdList());
              tmpInput->createPerkInput(d->getUsablePerk(skill->getParam("id"), skill->getParam("level").toInt()),
                                        _c->getPerkNumberForSkill(i));
              tmpInput->updateInput(skill);
              _skillI.append(tmpInput);
              //Add everything to the gridlayout
              tmpLayout->addWidget(new QLabel("Nom"), 0, 0);
              tmpLayout->addWidget(new QLabel("Niveau"), 0, 1);
              tmpLayout->addWidget(new QLabel("Spécial"), 0, 2);
              tmpLayout->addWidget(new QLabel("Vitesse"), 0, 3);
              tmpLayout->addWidget(new QLabel("Type"), 0, 4);
              tmpLayout->addWidget(_skillI[i]->level, 1, 1);
              tmpLayout->addWidget(_skillI[i]->special, 1, 2);
              tmpLayout->addWidget(_skillI[i]->speed, 1, 3);
              tmpLayout->addWidget(_skillI[i]->type, 1, 4);
              tmpLayout->addWidget(_skillI[i]->name,1, 0);
              //Now we add the perks (they have been filled with createPerkInput() earlier
              for(int j=0;j<_skillI[i]->perkList.size();j++)
              {
                  tmpLayout->addWidget(_skillI[i]->perkList[j], 2+j, 0);
                  tmpLayout->addWidget(_skillI[i]->perkLevel[j], 2+j, 1);
                  tmpLayout->addWidget(_skillI[i]->perkDesc[j], 2+j, 2, 1, -1);
              }
              //I'm not actually sure i need to access those later, but just to be sure i'll put them somewhere
              _skillInputLayout.append(tmpLayout);
              _skillInputBox.append(tmpBox);
              _skillInputBox[i]->setLayout(_skillInputLayout[i]);
              if(i%2 == 0)//We want to put 2 skills by line (cuz it's fancier), so ... different case
              {
                  _skillGrid->addWidget(_skillInputBox[i], i/2, 0, 1, 1, Qt::AlignTop);
              }
              else
              {
                  _skillGrid->addWidget(_skillInputBox[i], (i-1)/2, 1, 1 , 1, Qt::AlignTop);
              }
              connect(_skillI[i]->name, SIGNAL(currentIndexChanged(int)), this, SLOT(onSkillChanged()));
          }
          _skillBox->setLayout(_skillGrid);
          qDebug() << "updateSkillBoxes() finished";
      }
      
      void CGenerator::onSkillChanged()
      {
          qDebug() << "onSkillChanged() started";
          //We need to find which skill has been updated !
          for(int i=0;i<_skillI.size();i++)
          {
              QString newId = _skillI[i]->name->itemData(_skillI[i]->name->currentIndex()).toString();
              if(newId != _c->getSkill()[i]->getParam("id"))
              {
                  _c->updateSkill(i, newId);
                  CSkillInput *input;
                  input = _skillI[i];
                  _c->setSkillParam(i, "level", QString::number(input->level->value()));
                  _c->setSkillParam(i, "special",  input->special->itemData(input->special->currentIndex()).toString());
                  _c->updatePerkNumber(i, _c->getPerkNumberForSkill(i));
                  updateSkillBoxes();
              }
          }
          qDebug() << "onSkillChanged() finished";
      }
      

      CSkillInput代码:

      CSkillInput::CSkillInput(QStringList skillName, QStringList skillId)
      {
          name = new QComboBox;
          for(int i=0;i<skillName.size();i++)
          {
              name->addItem(skillName[i], skillId[i]);
          }
          speed = new QComboBox;
          speed->addItem("Rapide","f");
          speed->addItem("Moyen", "m");
          speed->addItem("Lent", "s");
          speed->setEnabled(false);
          type = new QComboBox;
          type->addItem("Martial", "w");
          type->addItem("Magique", "m");
          type->addItem("Divers", "d");
          type->setEnabled(false);
          special = new QComboBox;
          special->addItem("Rien", "n");
          special->addItem("Talent", "t");
          special->addItem("Don", "g");
          level = new QSpinBox;
          level->setMaximum(10);
      }
      
      CSkillInput::~CSkillInput()
      {
          this->name->disconnect();
      }
      
      void CSkillInput::createPerkInput(QList<CPerk *> perks, qint32 perkNumber)
      {
          //First we need to make a list of the perks name
          for(int i=0;i<perkNumber;i++)
          {
              //Kinda ugly but it's because we need to generate differents object
              QComboBox *tmpList = new QComboBox;
              for(int i=0;i<perks.size();i++)
              {
                  tmpList->addItem(perks[i]->getParamStr("name"), perks[i]->getParamStr("id"));
              }
              QSpinBox *tmpLevel = new QSpinBox;
              QLineEdit *tmpDesc = new QLineEdit;
              tmpLevel->setValue(perks[0]->getParamInt("level"));
              tmpLevel->setReadOnly(true);
              tmpDesc->setText(perks[0]->getParamStr("desc"));
              tmpDesc->setToolTip(perks[0]->getParamStr("desc"));
              perkList << tmpList;
              perkLevel << tmpLevel;
              perkDesc << tmpDesc;
          }
      }
      
      void CSkillInput::updateInput(CUSkill *skill)
      {
          if(skill->getParam("id") != name->itemData(name->currentIndex()))
          {
              name->setCurrentIndex(name->findData(skill->getParam("id")));
          }
          level->setValue(skill->getParam("level").toInt());
          speed->setCurrentIndex(speed->findData(skill->getParam("speed")));
          special->setCurrentIndex(special->findData(skill->getParam("special")));
          type->setCurrentIndex(type->findData(skill->getParam("type")));
      }
      

      标题(为了清晰起见,删除了CGenerator中的一些不相关的内容)

      class CSkillInput : public QObject
      {
          Q_OBJECT
      public:
          CSkillInput(QStringList skillName, QStringList skillId);
          ~CSkillInput();
      
          void createPerkInput(QList<CPerk *> perks, qint32 perkNumber);
          void updateInput(CUSkill *skill);
      
          QPointer<QComboBox> name;
          QPointer<QComboBox> speed;
          QPointer<QComboBox> type;
          QPointer<QComboBox> special;
          QPointer<QSpinBox> level;
          QList<QPointer<QComboBox > > perkList;
          QList<QPointer<QSpinBox > > perkLevel;
          QList<QPointer<QLineEdit > > perkDesc;
      };
      
      class CGenerator : public QWidget
      {
          Q_OBJECT
      public:
          CGenerator(CData *data);
          CData *d;
      
      private:
          CCharacter *_c;
          QGridLayout *_skillGrid;
          QGroupBox *_skillBox;
          QList<QPointer<QGridLayout> > _skillInputLayout;
          QList<QPointer<QGroupBox> > _skillInputBox;
          QList<QPointer<CSkillInput> > _skillI;
      private slots:
          void onSkillChanged();
          void updateSkillBoxes();
      };
      

      快速图解释我的用户界面:http://i.stack.imgur.com/SDHE2.png

      最后,我在segfault上的gdb堆栈:

      (gdb) bt
      #0  QComboBoxPrivate::itemText (this=this@entry=0xbf2540, index=...) at widgets/qcombobox.cpp:1287
      #1  0x00007ffff769e58f in QComboBoxPrivate::_q_emitCurrentIndexChanged (this=this@entry=0xbf2540, index=...)
          at widgets/qcombobox.cpp:1279
      #2  0x00007ffff769e8eb in QComboBoxPrivate::setCurrentIndex (this=this@entry=0xbf2540, mi=...) at widgets/qcombobox.cpp:2049
      #3  0x00007ffff769eb4f in QComboBox::setCurrentIndex (this=this@entry=0xca4450, index=index@entry=2) at widgets/qcombobox.cpp:2025
      #4  0x00007ffff76a2f06 in QComboBox::wheelEvent (this=0xca4450, e=0x7fffffffd7e0) at widgets/qcombobox.cpp:3096
      #5  0x00007ffff7306748 in QWidget::event (this=0xca4450, event=0x7fffffffd7e0) at kernel/qwidget.cpp:8775
      #6  0x00007ffff72b348c in QApplicationPrivate::notify_helper (this=this@entry=0x659590, receiver=receiver@entry=0xca4450, 
          e=e@entry=0x7fffffffd7e0) at kernel/qapplication.cpp:4570
      #7  0x00007ffff72bb4fb in QApplication::notify (this=<optimized out>, receiver=0xca4450, e=0x7fffffffd7e0)
          at kernel/qapplication.cpp:4168
      #8  0x00007ffff6d8371d in QCoreApplication::notifyInternal (this=0x7fffffffe130, receiver=0xca4450, event=0x7fffffffd7e0)
          at kernel/qcoreapplication.cpp:955
      #9  0x00007ffff732cb49 in sendSpontaneousEvent (event=<optimized out>, receiver=<optimized out>)
          at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:234
      #10 QETWidget::translateWheelEvent (this=0x7fffffffd7e0, global_x=12526912, global_y=12486272, delta=12750704, buttons=..., 
          modifiers=..., orient=Qt::Vertical) at kernel/qapplication_x11.cpp:4578
      #11 0x00007ffff73309c8 in QETWidget::translateMouseEvent (this=this@entry=0x7fffffffe0b0, event=event@entry=0x7fffffffdc70)
          at kernel/qapplication_x11.cpp:4355
      #12 0x00007ffff732ee2c in QApplication::x11ProcessEvent (this=0x7fffffffe130, event=event@entry=0x7fffffffdc70)
          at kernel/qapplication_x11.cpp:3663
      #13 0x00007ffff7357ed2 in x11EventSourceDispatch (s=0x65c320, callback=0x0, user_data=0x0) at kernel/qguieventdispatcher_glib.cpp:146
      #14 0x00007ffff56f8c5d in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
      #15 0x00007ffff56f8f48 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
      #16 0x00007ffff56f8ffc in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
      #17 0x00007ffff6db2d1d in QEventDispatcherGlib::processEvents (this=0x65add0, flags=...) at kernel/qeventdispatcher_glib.cpp:425
      #18 0x00007ffff7357f96 in QGuiEventDispatcherGlib::processEvents (this=<optimized out>, flags=...)
          at kernel/qguieventdispatcher_glib.cpp:204
      #19 0x00007ffff6d82271 in QEventLoop::processEvents (this=this@entry=0x7fffffffe050, flags=...) at kernel/qeventloop.cpp:149
      ---Type <return> to continue, or q <return> to quit---
      #20 0x00007ffff6d825d5 in QEventLoop::exec (this=this@entry=0x7fffffffe050, flags=...) at kernel/qeventloop.cpp:204
      #21 0x00007ffff6d88059 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1227
      #22 0x0000000000408ad5 in main (argc=1, argv=0x7fffffffe238) at ../../../../code/kustom/kustom-sheet-creator/main.cpp:34
      

0 个答案:

没有答案