Mysterious SegFault only if not run after QMake
So I've been trying to find a solution to this problem on the forums, but I can't seem to find anything similar. I can post code if necessary, but my project is approaching 2000 lines of code, so I'd rather not. I am using pure code, no designer or anything (i don't know if it makes a difference).
This just started today without me adding any code (that I can remember anyway). When I close my project (either use my button that calls the main window's close() function or use alt+f4, I get a segfault. I used the debugger to find out it is happening while everything is being deconstructed (after my main returns). I put deconstructors in all of the classes I made personally and a printf with a break point, but none of those seem to be the problem: I watched every single instance of my personally defined objects be deconstructed (I even traced the address). This led me to believe that it must be one of the other class I'm using that are not of my making (QSlider, QPushButton, QPixMap, QLabel).
I tried a clean and build, which didn't work. Then I read that a QMake can fix it. I ran QMake and the first time I ran it, no segfault. Second time I ran it (without QMake immediately before it), segfault. Also, if I don't use the debugger, there appears to be no ill side-effects, but I still think a segfault is bad regardless.
Any thoughts? please ask me questions if you want me to clarify. Thanks beforehand!
welcome to devnet
qmake cannot cure your segmentation fault per se. It may help to rebuild everything and therefore, it may cure problems arising from conflicts in your object/header/code structure.
This looks like a typic pointer problem. However, it might be something else. Since the problem seems to start within destruction of the objects, it may be for instance a pointer deleted twice. You may want to check for such a possibility.
The problem is that it seems to have shown up out of nowhere. When I went to bed yesterday, it ran fine and when i woke up this morning it behaved as i described. That is what is most confusing. What are the best ways to check for a pointer being deleted twice and why would running QMake make the next run work, but not the one after it? I've never really had to run QMake so I'm not all that familiar with what it does.
(and thanks for the welcome)
Are you deleting pointers yourself?
This setup would produce a crash:
void foo ()
double *ptr = new clsObject;
Simply settings the pointer to zero prevents the problem.
void foo ()
double *ptr = new clsObject;
ptr = 0;
The explanation for qmake preventing the crash in a first start is an indication of a pointer problem. However, it is than actually a pointer pointing somewhere. If it happens to point to memory holding 0 the delete will not cause a problem as shown in the little example above. Starting the program a second time the memory is changed and suddenly the pointer may hold a numerical value.
Are you using pointers? Check them out. Probably one of them is not initialize by allocating memory.
I'm using quite a few pointers. I will take a look to see. At first glance, everything is initialized at some point or another; the only thing that gets deleted in the code is stuff in a QList that can be dynamically added and removed (and have been in the project forever and i use deleteLater()). Not to mention that that QList starts empty and I can get my segfault by just running and then closing. What are the different ways besides 'delete' that could cause issues with a pointer being deleted twice?
Just the use of a pointer not initialized is always very unhealthy.
Because the problem comes up when destructing the application/objects triggered my guess that it is delete related. Rethinking it is probably not a pointer deleted twice. it is more likely that you delete a pointer which does not point to memory.
However, you are able to reproduce in the debugger. Check out, if it crashes always in the same area of your code. Try to narrow down to actual location where the segfault is triggered.
The debugger is useless to me. Since it happens after the main returns and is presumable during destructors, the stack is a bunch of question marks and it points a command in the disassembler. I can't read the code effectively there. If you want I can copy some here.
Here is the code involving the deleting:
sounds is a QList containing SoundInstances(which is my own class). This is part of a 'new' function that empties the list.
The function that gets rid of something from sound one at a time does it in the exact same manner.
There are no other references to the sound except a pointer to the last one that was selected (which is set to 0).
Every other pointer i have is initialized and never deleted;
clear() is releasing the memory of the QList. The QList contained the pointers. Presumably something is done prior to the deleteLater() will be done and you got your crash.
I don't think that's the issue. The SoundInstance is actually an extension of a PushButton so it can be displayed, so if you just call sounds->clear(), the object still exists and still appears in the window. However, if you just call the loops of deleteLater(), then the QList still contains the pointer. Both appear to be necessary.
I hope i don't sound too flustered, this is just driving me crazy.
Did you actually try to comment out the clear?
Your objects are being deleted by deleteLater. If I am not completely mistaken, you are pulling the carpet you are standing on with your clear.
btw I completely understand this driving you crazy. Would drive me crazy as well. :-(
So I commented everything out of my constructor so i get a blank window. When i close it, it still segfaults. No other code is running (I have breakpoints everywhere and nothing gets hit) and still I get a segfault on close.
This is certainly one way to taggle the problem. However, I hope you are not blindly commenting out in the constructor and forget the counterpart in the destructor. This most likely will generate additional segfaults as well.
Your strategy is absolutely correct, but do it in a calm manner. Think about it and the consequences in your code and especially that some leftovers do not create more problems. Panicking will not help at all. Sometimes it even helps to take a break and start freshly. Actually most of the time it does for me.
Ok, I know it's been a little while, but my problem persists in a weird way. My desructor for my main window is as follows:
if(workspace) delete workspace;
if(currentlySelected) delete currentlySelected;
if(shortcutPlay) delete shortcutPlay;
if(shortcutVolumeUp) delete shortcutVolumeUp;
if(shortcutVolumeDown) delete shortcutVolumeDown;
//layer 2 first
if(audemeLibraryAccess) delete audemeLibraryAccess;
if(addAudeme) delete addAudeme;
if(removeAudeme) delete removeAudeme;
if(testPlay) delete testPlay;
if(searchBox) delete searchBox;
if(rewind) delete rewind;
if(play) delete play;
if(pause) delete pause;
if(forward) delete forward;
if(volume) delete volume;
if(interactionHelp) delete interactionHelp;
if(interactionProperties) delete interactionProperties;
if(interactionFile) delete interactionFile;
if(interactionFileNew) delete interactionFileNew;
if(interactionFileOpen) delete interactionFileOpen;
if(interactionFileSaveAs) delete interactionFileSaveAs;
if(interactionFileSave) delete interactionFileSave;
if(interactionFileExit) delete interactionFileExit;
if(interactionFileChangeLibraryLocation) delete interactionFileChangeLibraryLocation;
if(interactionFileRefreshLibrary) delete interactionFileRefreshLibrary;
if(interactionPropertiesName) delete interactionPropertiesName;
if(interactionPropertiesNameField) delete interactionPropertiesNameField;
if(interactionPropertiesRelPath) delete interactionPropertiesRelPath;
if(interactionPropertiesRelPathField) delete interactionPropertiesRelPathField;
if(interactionPropertiesSampleRate) delete interactionPropertiesSampleRate;
if(interactionPropertiesSampleRateField) delete interactionPropertiesSampleRateField;
if(interactionPropertiesSamples) delete interactionPropertiesSamples;
if(interactionPropertiesSamplesField) delete interactionPropertiesSamplesField;
if(interactionPropertiesLength) delete interactionPropertiesLength;
if(interactionPropertiesLengthField) delete interactionPropertiesLengthField;
if(interactionPropertiesStartTime) delete interactionPropertiesStartTime;
if(interactionPropertiesStartTimeField) delete interactionPropertiesStartTimeField;
//then layer 1
if(audemeLibrary) delete audemeLibrary;
if(controlPanel) delete controlPanel;
if(interactionPane) delete interactionPane;
delete  channelButtons;
if(channels) delete  channels;
if(timer) delete timer;
if(timerCount) delete timerCount;
if(timerMax) delete timerMax;
if(timerCountImage) delete timerCountImage;
Every single pointer is being checked and, if it exists, is deleted. The weird thing is that it still segfaults at the end, but it also stops on the one line where I've expanded (delete  channelButtons;). It stops there and does nothing when debugging like it is about to throw a segfault, but does not. It will then reach the breakpoint on the last line before segfaulting. Any thoughts as to why this might be happening as it is?
[quote author="mccurrab" date="1332519524"]So I commented everything out of my constructor so i get a blank window. When i close it, it still segfaults. No other code is running (I have breakpoints everywhere and nothing gets hit) and still I get a segfault on close.[/quote]
Am I correct in assuming that you've commented out the items, but still have the destructor as written above? If so, are the different object pointers (workspace, currentlySelected, et al.) being initialized to 0? If not, then they'll have random values, and as such, the if statements in the destructors will still evaluate as true and the deletes will be called.
(I see now that Koahnig asked the same question two posts up, but I don't think you addressed it in your reply.)
Everything is at least being initialized to 0, though most are being initialized to an object. My previous segfault came from channelButtons being deleted after channels. channels is an array of QLabels that are the parent of the corresponding QImageButton (a simple class extending QPushButton of my own creation) in channelButtons. This was an obvious mistake that I should have caught and is now fixed by switching the order being deleted, but as I said, upon exiting the program, it stops on the delete  channelButtons line, but does not segfault like it used to
Then of course it goes past my destructor (which seems unlikely since every other destructor should have already been called since the main window is the highest in the parent hierarchy) to segfault on something i don't know.
May be kind of late in the game to ask, but a couple of thoughts cross my mind...
Could/should you be taking better advantage of Qt's widget parenting system to let your destructor handle deleting all of the child objects itself, rather than you having to delete them manually? By creating them with "new whateverWidget(this)" Your MainWindow will clean them and their children up for you.
Why have a C-style array of QLabel pointers? Why not use a QList<QLabel *>?
I used to not have any destructors and just let it do everything by default. Unfortunately, it led to having a segfault that I could do nothing about. So i made the destructors myself.
I was thinking about switching to using QList, but I started with an array because i am more used to arrays than QLists. At this point I think I am going to convert them, but I'm not sure if it will fix this issue.
Qt's parent/child mechanism isn't broken. If it was leading to a segfault, then it was more than likely caused by mishandling of a pointer somewhere along the way. Adding your own destructors won't fix that problem. Even worse, it may mask the problem, thus making it a lot harder to diagnose.
Well that might be true (I wasn't fond of having it write my own destructors), but the only 'mishandling' of pointers comes from the dependency of channelButtons on channels. However, there's no way to remove this dependency that I can see since I need access to those buttons from the main window. Can you think of a solution (because believe me I'm getting tired of this problem)?