2013-11-14 30 views
1

我的实际使用情况是平凡的,所以我提供再现分段错误的一个小例子:促进CustomQScrollArea分段故障

我有类CustomScrollArea继承QScrollArea:

customscrollarea.h

class CustomScrollArea : public QScrollArea 
{ 
    Q_OBJECT 
public: 
    explicit WarxingScrollArea(QWidget* parent=0); 
    void segFaultThrowingMethod(); 
private: 
    QLabel* dynamicallyCreatedLabel; 
}; 

customscrollarea.cpp

CustomScrollArea::CustomScrollArea(QWidget* parent) : QScrollArea(parent) 
{ 
    dynamicallyCreatedLabel = new QLabel; 
    setWidget(dynamicallyCreatedLabel); 

    //this call will _not_ cause a seg fault 
    segFaultThrowingMethod(); 
} 

void CustomScrollArea::segFaultThrowingMethod() 
{ 
    dynamicallyCreatedLabel->setText("Some text"); 
} 

我有以下源一个MainWindow类:

mainwindow.h

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 
public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 
private: 
    Ui::MainWindow *ui; 
}; 

mainwindow.cpp

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); 

    //this call will cause a seg fault 
    ui->customScrollArea->segFaultThrowingMethod(); 
} 

MainWindow::~MainWindow() 
{ 
    delete ui; 
} 

对于主窗口的的.ui文件包含一个QScrollArea提升为CustomQScrollArea。它的名字是“customScrollArea”。

当我启动应用程序时,CustomScrollArea :: segFaultThrowingMethod()的第一次调用发生在CustomScrollArea的Ui :: MainWindow :: customScrollArea的构造函数中,并且没有发生事件传递。但是,当MainWindow调用ui-> customScrollArea-> segFaultThrowingMethod()时,会发生分段错误。

请注意,分段错误不是由于CustomScrollArea :: dynamicallyCreatedLabel为空(如建议here)所致。我得到的最好线索是,如果MainWindow动态实例化CustomScrollArea而不是从Ui :: MainWindow获取它,则不会发生此问题。不过,我希望能够在Qt Designer中使用QScrollAreas提升为CustomScrollAreas。

感谢您的帮助!

+0

你尝试过使用调试器吗?你的发展环境? –

+0

使用VC2010在Windows上使用Qt Creator。在两个segFaultThrowingMethod()的调用中,调试器都指示了dynamicallyCreatedLabel是相同的非空值。从Pavel的回答可以看出,实际的空指针一定是Qt架构中更深层的地方。我的编译器和构建这些Qt库的编译器之间必然存在一些差异,因为我无法步入它们。 – phizla

回答

1

Qt Designer会自动为任何滚动区域创建一个内部控件。这个小部件在默认情况下被称为“scrollAreaWidgetContents”,并且在Qt Designer的小部件树中可见。 Ui::MainWindow Designer生成的类为您创建CustomScrollArea并执行setWidget来设置其内容。调用CustomScrollArea构造函数后,此操作在setupUi中发生。但是QScrollArea拥有其内部小部件的所有权。当调用setWidget时,先前滚动区域的内部小部件(如果有的话)被解散并销毁。所以在setupUi之内调用setWidget会导致先前创建的QLabel被破坏,而dynamicallyCreatedLabel指针变为无效。

无法在Qt Designer中删除“scrollAreaWidgetContents”。解决方法是将窗口小部件添加到窗体并将其提升到CustomScrollArea类。 Qt Designer不会知道CustomScrollArea实际上是一个QScrollArea,不会自己调用setWidget。唯一的副作用是您将无法设置滚动区域特定的属性并访问Qt Designer中的插槽。但是你可以通过你的代码来做到这一点,所以这不是一个大问题。

+0

该解决方法奏效;谢谢!我想另一种解决方案是推迟动态生成标签的创建,直到在CustomScrollArea的构造函数之后。 – phizla

+0

我刚从这里开始,所以我不能投票 - 对不起。 – phizla