I've a simple class with these, also simple, constructors:
audio::audio() {
channels = NULL;
nChannels = 0;
}
audio::audio(const char* filename) {
audio();
getFromFile(filename);
}
(Before it was audio():channels(NULL), nChannles(0), loaded(false){...
, I'll say later why this changed...). The function getFromFile
starts like this:
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;
...
As you can see, it checks if loaded
is true and if it is runs some delete
(s) on internal buffers. Of course, as you can see from the constructor, at first run loaded
is false, then the 2nd constructor will call the first constructor and then have loaded = false
.
If I run this class in a simple command line app, everything runs fine. But if I put it in a Qt application, precisely in a slot that does this:
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();
}
[...]
it will have channels != NULL
(after invoking the 2nd constructor) and try to delete a pointer that is not assigned (resulting in a segmentation fault). Using GDB I found that channels
is set to some strange value, and nChannels
too... This smells like a race condition, but apparently doesn't seem to be the case. I put a check in the slot to see if aud != NULL
, to avoid this. Do you have any ideas? Why is it happening? I tried to use Valgrind and it says that at channels != NULL
I am trying to do a conditional jump with an uninitialized value! How can it be? What about the constructors?