我有一个简单的类,这些也是简单的构造函数:
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
我试图用未初始化的值进行条件跳转!怎么会这样?那些构造函数呢?
答案 0 :(得分:9)
问题出在audio::audio(const char* filename)
构造函数中。第一个语句是audio();
我相信你试图调用默认构造函数。但是,C ++不允许一个ctor调用另一个ctor。所以你有未初始化的指针。如果你想做这样的事情,写一个名为init()
的私有方法,并从两个构造函数中调用它。 audio();
语句使用默认ctor创建一个临时(未命名)音频对象,该语句在此语句后立即销毁。因此,您在此之后访问的对象是一个具有未初始化指针的不同对象。