After my application ends, it returns 1 which should mean that something isn't right. However, I can't tell what it is.
Probably I am not freeing something correctly. In allegro.log I have the following text near the end:
d3d D d3d_disp.cpp:904 d3d_destroy_display_internals [ 41.01223] waiting for display 00327FF0's thread to end
d3d W d3d_disp.cpp:616 d3d_destroy_device [ 41.02325] d3d_destroy_device: ref count not 0
d3d I d3d_disp.cpp:1522 d3d_display_thread_proc [ 41.07369] d3d display thread exits
is this the cause that code 1 is returned? and if so, what is it caused by? I guess that something still referencing d3d device has to do with it. But what? Should I destroy all the bitmaps before destroying the allegro_display? or vice versa? and what about the fonts?
I am pretty sure that I eventually free everything. Should I care at all about this return code?
Do you have a return statement in your main function?
No. And it's void main() anyway. I guess allegro substitutes it for something and it's allegro's return code, not mine.
What's funny here, Dizzy Egg?
What did you expect if you declare your main as void? A nice '0' to be returned???
void main is invalid C/C++[1].
Well. Thank you very much for noting that. I changed that.
However, i think it did return 0 in the past if all the threads had returned 0.
But the problem still stays: last thread returns 1. (I am not creating threads myself, these are all allegro threads). Should I worry about it?
--
I am pretty sure it's the d3d thread mentioned in the log.
It's not the d3d thing, that's just a warning. You say you're seeing the return code of 1 in the debugger? What else does the debugger say? Is there a crash or an assertion or exception thrown?
No. No crash and nothing is mentioned. That's why I went to allegro.log and that's the only thing that I found here which seemed abnormal.
Yes I see the return code in the debugger after everything ends.
By the way, it's pretty strange. Now I changed everything to the way you say it should be, with int main(int argc, char **argv) and ending with return 0.
But the funny thing is, the application still returns 1.
The thread 0x934 has exited with code 0 (0x0).
'Mirrord.exe' (Win32): Unloaded 'C:\Windows\SysWOW64\powrprof.dll'
The thread 0x10f8 has exited with code 0 (0x0).
The thread 0xce8 has exited with code 1 (0x1).
'Mirrord.exe' (Win32): Unloaded 'C:\Windows\SysWOW64\nvd3dum.dll'
'Mirrord.exe' (Win32): Unloaded 'C:\Windows\SysWOW64\d3d9.dll'
'Mirrord.exe' (Win32): Unloaded 'C:\Windows\SysWOW64\d3d8thk.dll'
No memory leaks detected.
Visual Leak Detector is now exiting.
The program '[3456] Mirrord.exe' has exited with code 1 (0x1).
How about putting a message box or a printf("bye\n"); just before that final return 0? Does it show that message on exit? Of course you'd have to run it from a console to see a printf.
I'm pretty sure it runs up to the very end and executes every last line.
But I did what you asked. Yes, the message is shown.
UPDATE: I attached allegro.log to the first post.
Could be a signal handler called "on exit" because a SIGSEGV happens for example and/or something installed by atexit() crashes. Can you try putting a breakpoint on libc's exit() ? If something is calling exit(1), you'd see in the call stack.
Hello, Audric and thank you for your input.
Could you explain to me, how do I put a breakpoint on libc's exit?
UPDATE: OK, I did it this way: I made an empty function, put a breakpoint on it and then passed it to atexit().
The strange thing is that when I check value of the argument "code" of the exit(int code) function, which is up the call stack, it shows 0 in the debugger. Up to the end. And then visual studio says it exited with code 1...
I'm not sure I put the breakpoint when you suggested, though.
Try setting a breakpoint anywhere after your program starts up fully. Check which threads are running (don't know how in VS, but should be possible.) Not their id/address and what they're doing. Then when the app exits check which thread that returns 1 corresponds to the one you checked on earlier.
Your test already shows that the issue happens after main() returns, after it executes the function you hooked on atexit(). Maybe then it executes another atexit() function that was registered before yours (by a library, usually).
I don't know about Visual Studio's debugger for C language, though if it has similar options as for C#, be sure to check in Debug/Exception menu: "Break on ..." everything : signals, caught exception, uncaught exception, runtime errors... everything it proposes.
If you do find a way to make it break on system functions of your choice, try stopping abort() in addition to exit().
Trent Gamblin
I have the following threads:
2928 0 Main Thread name: Mirrord.exe!MirrorApp::Init Normal
5676 0 Worker Thread name: GdiPlus.dll!DllRefCountSafeThreadThunk() location: GdiPlus.dll!BackgroundThreadProc Normal
1556 0 Worker Thread name: msvcr110d.dll!_threadstartex location: allegro-5.0.8-monolith-md-debug.dll!501c453e Normal
5684 0 Worker Thread name: nvd3dum.dll thread location: nvd3dum.dll!67319d84 Above Normal
When the program ends, the 0x162c thread returns with code 1, that is the second thread 5676.
Audric
The problem is, the return code 0 stays up to the end. I mean, I step through the whole program up to the line __crtExitProcess(code); after which the program ends. And even there it shows "the program exited with code 1", when I step over the program ends with code 1. I can't step into this function itself thought I get thrown into assembly.
How is that even possible? Could it be some memory corruption?
I have no idea what else to enable, I think it should break at every exception.
I think I found a way to break at function by its name, and I added breakpoints on abort and exit functions, but it doest break on abort. It breaks on exit, though.
UPDATE:
It seems that the application returns 1 when the last thread returns 1. If the last thread to end isn't this GDI thread, then I get return code 0.
Moreover, I just used this tutorial http://wiki.allegro.cc/index.php?title=Basic_tutorial_on_loading_and_showing_images and the GDI thread there also returns 1. However, the application itself returns what it is told to return.
Can you set a breakpoint in _al_shutdown_gdiplus? What happens if you don't init the image addon?
If I don't init the image addon the return code is 0.
Yes, I can put a breakpoint there. What am I looking for over there?
Gdiplus::GdiplusShutdown(gdiplusToken);
the gdiplusToken is 37445138
I'm not sure why the GdiPlus thread is returning 1. A temporary solution might be to call al_shutdown_image_addon before returning from main.
Shutting image addon down manually doesn't kill the gdi thread and it still only gets destroyed at exit (with code 1). Maybe some other addon uses it too?
What about a patch like this?
diff --git a/addons/image/iio.c b/addons/image/iio.c index d98716e..6ecbfe5 100644 --- a/addons/image/iio.c +++ b/addons/image/iio.c @@ -128,6 +128,10 @@ bool al_init_image_addon(void) void al_shutdown_image_addon(void) { iio_inited = false; + +#ifdef ALLEGRO_CFG_IIO_HAVE_GDIPLUS + _al_shutdown_gdiplus(); +#endif }
I'll probably have to compile allegro myself for that, right? or I could just place shutdown_gdi myself in my code?
Anyway, thank you very much, Trent. It seems it's nothing serious I should care about.
You can try calling _al_shutdown_gdiplus() yourself (you may have to declare it.)
It seems it's nothing serious I should care about.
This could be the tip of the iceberg in a allegro bug, so thank you for your persistence.