在Qt应用程序中使用时出现奇怪的类行为

时间:2009-11-21 15:32:51

标签: c++ qt

我有一个简单的类,这些也是简单的构造函数:

audio::audio() {
    channels = NULL;
    nChannels = 0;  
}

audio::audio(const char* filename) {
    audio();
    getFromFile(filename);
}

(在audio():channels(NULL), nChannles(0), loaded(false){...之前,我稍后会说为什么会改变......)。函数getFromFile的开头如下:

void audio::getFromFile(const char* filename) {
    baseUtils::dynVec<float> *chans;
    if (channels != NULL)
        deleteChannels();
    sox_format_t *in;
    sox_sample_t buff[AUDIO_CLASS_READ_SAMPLES];
    sox_sample_t sample;
...

如您所见,它检查loaded是否为真,以及是否在内部缓冲区上运行了一些delete。当然,正如您从构造函数中看到的那样,在第一次运行时loaded为false,然后第二个构造函数将调用第一个构造函数,然后使用loaded = false

如果我在一个简单的命令行应用程序中运行此类,一切运行正常。但是,如果我把它放在Qt应用程序中,恰好在一个插槽中执行此操作:

void buttonPushed() {

        QString s = QFileDialog::getOpenFileName();
        std::cout << "file choosen: " << s.toStdString() << "\n";
        sndfile = s.toStdString();
        if (aud == NULL){
            aud = new audio(sndfile.c_str());
            ui.widget->setAudio(aud);
            ui.widget->update();
        }
[...]

它将具有channels != NULL(在调用第二个构造函数之后)并尝试删除未分配的指针(导致分段错误)。使用GDB我发现channels被设置为一些奇怪的值,而nChannels也被设置为...这闻起来像一个竞争条件,但显然似乎并非如此。我在插槽中检查是否aud != NULL,以避免这种情况。你有什么想法?为什么会这样?我尝试使用Valgrind,它说在channels != NULL我试图用未初始化的值进行条件跳转!怎么会这样?那些构造函数呢?

1 个答案:

答案 0 :(得分:9)

问题出在audio::audio(const char* filename)构造函数中。第一个语句是audio();我相信你试图调用默认构造函数。但是,C ++不允许一个ctor调用另一个ctor。所以你有未初始化的指针。如果你想做这样的事情,写一个名为init()的私有方法,并从两个构造函数中调用它。 audio();语句使用默认ctor创建一个临时(未命名)音频对象,该语句在此语句后立即销毁。因此,您在此之后访问的对象是一个具有未初始化指针的不同对象。