Skip to content

Commit

Permalink
Define wxDEBUG_LEVEL in both debug and release builds as 1.
Browse files Browse the repository at this point in the history
By default include assertions and debug logging in both debug and release
builds but disable them in application release builds (when NDEBUG is
defined).

Also update (more accurately, replace) debugging overview.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61886 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
  • Loading branch information
vadz committed Sep 12, 2009
1 parent db5a2bf commit 7d9550d
Show file tree
Hide file tree
Showing 11 changed files with 275 additions and 155 deletions.
2 changes: 1 addition & 1 deletion docs/doxygen/groups/funcmacro_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

/**
@defgroup group_funcmacro_debug Debugging
@defgroup group_funcmacro_debug Debugging macros
@ingroup group_funcmacro
Useful macros and functions for error checking and defensive programming.
Expand Down
194 changes: 81 additions & 113 deletions docs/doxygen/overviews/debugging.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/////////////////////////////////////////////////////////////////////////////
// Name: debugging.h
// Purpose: topic overview
// Author: wxWidgets team
// Author: Vadim Zeitlin
// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
// RCS-ID: $Id$
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
Expand All @@ -10,89 +11,93 @@
@page overview_debugging Debugging
Classes, functions and macros: wxDebugContext, wxObject, wxLog,
@ref group_funcmacro_log, @ref group_funcmacro_debug
Classes, functions and macros: wxLog, @ref group_funcmacro_log, @ref group_funcmacro_debug
Various classes, functions and macros are provided in wxWidgets to help you debug
your application. Most of these are only available if you compile both wxWidgets,
your application and @e all libraries that use wxWidgets with the __WXDEBUG__ symbol
defined. You can also test the __WXDEBUG__ symbol in your own applications to execute
code that should be active only in debug mode.
@li @ref overview_debugging_dbgctx
@li @ref overview_debugging_dbgmacros
@li @ref overview_debugging_logging
@li @ref overview_debugging_dbgctx2
<hr>
@section overview_debugging_dbgctx wxDebugContext
wxDebugContext is a class that never gets instantiated, but ties together
various static functions and variables. It allows you to dump all objects to that stream,
write statistics about object allocation, and check memory for errors.
It is good practice to define a wxObject::Dump member function for each class you derive
from a wxWidgets class, so that wxDebugContext::Dump can call it and
give valuable information about the state of the application.
If you have difficulty tracking down a memory leak, recompile
in debugging mode and call wxDebugContext::Dump and wxDebugContext::PrintStatistics at
appropriate places. They will tell you what objects have not yet been
deleted, and what kinds of object they are. In fact, in debug mode wxWidgets will automatically
detect memory leaks when your application is about to exit, and if there are any leaks,
will give you information about the problem. (How much information depends on the operating system
and compiler -- some systems don't allow all memory logging to be enabled). See the
memcheck sample for example of usage.
For wxDebugContext to do its work, the @e new and @e delete operators for wxObject
have been redefined to store extra information about dynamically allocated objects
(but not statically declared objects).
This slows down a debugging version of an application, but can
find difficult-to-detect memory leaks (objects are not
deallocated), overwrites (writing past the end of your object) and
underwrites (writing to memory in front of the object).
If debugging mode is on and the symbols wxUSE_GLOBAL_MEMORY_OPERATORS and
wxUSE_DEBUG_NEW_ALWAYS are set to 1 in setup.h, 'new' is defined to be:
@code
#define new new(__FILE__,__LINE__)
@endcode
All occurrences of 'new' in wxWidgets and your own application will use
the overridden form of the operator with two extra arguments. This means that
the debugging output (and error messages reporting memory problems) will tell you what
file and on what line you allocated the object. Unfortunately not all
compilers allow this definition to work properly, but most do.
@section overview_debugging_dbgmacros Debug macros
You should also use @ref group_funcmacro_debug as part of a 'defensive programming'
strategy, scattering wxASSERTs liberally to test for problems in your code as early as
possible.
Forward thinking will save a surprising amount of time in the long run.
#wxASSERT is used to pop up an error message box when a condition
is not @true. You can also use #wxASSERT_MSG to supply your
own helpful error message. For example:
your application: @ref overview_debugging_dbgmacros allow you to insert various
checks in your application which can be compiled out or disabled in release
builds but are extremely useful while developing and @ref
overview_debugging_logging which are not limited to debugging but are also
useful for inserting traces into your application code. Both assertions and
debug logging are also used by wxWidgets itself so you may encounter them even
if you don't use either of these features yourself.
@section overview_debugging_config Configuring debugging support
Starting with wxWidgets 2.9.1 debugging features are always available by
default (and not only in a special "debug" build of the library) and you need
to predefine wxDEBUG_LEVEL symbol as 0 when building both the library and your
application to remove them completely from the generated object code. However
the debugging features are disabled by default when the application itself is
built with @c NDEBUG defined (i.e. in "release" or "production" mode) so there
is no need to do this, unless the resources of the system your application will
be running on are unusually constrained (notice that when asserts are disabled
their condition is not even evaluated so the only run-time cost is a single
condition check and the extra space taken by the asserts in the code).
This automatic deactivation of debugging code is done by IMPLEMENT_APP() macro
so if you don't use you may need to explicitly call wxDISABLE_DEBUG_SUPPORT()
yourself.
Also notice that it is possible to build your own application with a different
value of wxDEBUG_LEVEL than the one which was used for wxWidgets itself. E.g.
you may be using an official binary version of the library which will have
been compiled with default @code wxDEBUG_LEVEL == 1 @endcode but still predefine
wxDEBUG_LEVEL as 0 for your own code.
On the other hand, if you do want to keep the asserts even in production
builds, you will probably want to override the handling of assertion failures
as the default behaviour which pops up a message box notifying the user about
the problem is usually inappropriate. Use wxSetAssertHandler() to set up your
own custom function which should be called instead of the standard assertion
failure handler. Such function could log an appropriate message in the
application log file or maybe notify the user about the problem in some more
user-friendly way.
@section overview_debugging_dbgmacros Assertion macros
wxASSERT(), wxFAIL(), wxCHECK() as well as their other variants (see @ref
group_funcmacro_debug) are similar to the standard assert() macro but are more
flexible and powerful. The first of them is equivalent to assert() itself, i.e.
it simply checks a condition and does nothing if it is true. The second one is
equivalent to checking an always false condition and is supposed to be used for
code paths which are supposed to be inaccessible (e.g. @c default branch of a
@c switch statement which should never be executed). Finally, the wxCHECK()
family of macros verifies the condition just as wxASSERT() does and performs
some action such returning from the function if it fails -- thus, it is useful
for checking the functions preconditions.
All of the above functions exist in @c _MSG variants which allow you to provide
a custom message which will be shown (or, more generally, passed to the assert
handler) if the assertion fails, in addition to the usual file and line number
information and the condition itself.
Example of using an assertion macro:
@code
void MyClass::MyFunction(wxObject* object)
void GetTheAnswer(int *p)
{
wxASSERT_MSG( (object != NULL), "object should not be NULL in MyFunction!" );
wxCHECK_RET( p, "pointer can't be NULL in GetTheAnswer()" );
...
*p = 42;
};
@endcode
The message box allows you to continue execution or abort the program. If you are running
the application inside a debugger, you will be able to see exactly where the problem was.
If the condition is false, i.e. @c p is @NULL, the assertion handler is called
and, in any case (even when wxDEBUG_LEVEL is 0), the function returns without
dereferencing the NULL pointer on the next line thus avoiding a crash.
The default assertion handler behaviour depends on whether the application
using wxWidgets was compiled in release build (with @c NDEBUG defined) or debug
one (without) but may be changed in either case as explained above. If it
wasn't changed, then nothing will happen in the release build and a message box
showing the information about the assert as well as allowing to stop the
program, ignore future asserts or break into the debugger is shown. On the
platforms where wxStackWalker is supported the message box will also show the
stack trace at the moment when the assert failed often allowing you to diagnose
the problem without using the debugger at all. You can see an example of such
message box in the @ref page_samples_except.
Expand All @@ -103,42 +108,5 @@ debug mode; it will do nothing for non-debugging code.
@section overview_debugging_dbgctx2 wxDebugContext overview
Class: wxDebugContext
wxDebugContext is a class for performing various debugging and memory tracing operations.
This class has only static data and function members, and there should be
no instances. Probably the most useful members are SetFile (for directing output
to a file, instead of the default standard error or debugger output);
Dump (for dumping the dynamically allocated objects) and PrintStatistics
(for dumping information about allocation of objects). You can also call
Check to check memory blocks for integrity.
Here's an example of use. The SetCheckpoint ensures that only the
allocations done after the checkpoint will be dumped.
@code
wxDebugContext::SetCheckpoint();
wxDebugContext::SetFile("c:\\temp\\debug.log");
wxString *thing = new wxString;
char *ordinaryNonObject = new char[1000];
wxDebugContext::Dump();
wxDebugContext::PrintStatistics();
@endcode
You can use wxDebugContext if __WXDEBUG__ is defined, or you can use it
at any other time (if wxUSE_DEBUG_CONTEXT is set to 1 in setup.h). It is not disabled
in non-debug mode because you may not wish to recompile wxWidgets and your entire application
just to make use of the error logging facility.
@note wxDebugContext::SetFile has a problem at present, so use the default stream instead.
Eventually the logging will be done through the wxLog facilities instead.
*/

16 changes: 13 additions & 3 deletions include/wx/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,24 @@
#include "wx/cmdargs.h" // for wxCmdLineArgsArray used by wxApp::argv
#include "wx/init.h" // we must declare wxEntry()
#include "wx/intl.h" // for wxLayoutDirection
#include "wx/log.h" // for wxDISABLE_DEBUG_LOGGING_IN_RELEASE_BUILD()

class WXDLLIMPEXP_FWD_BASE wxAppConsole;
class WXDLLIMPEXP_FWD_BASE wxAppTraits;
class WXDLLIMPEXP_FWD_BASE wxCmdLineParser;
class WXDLLIMPEXP_FWD_BASE wxEventLoopBase;
class WXDLLIMPEXP_FWD_BASE wxLog;
class WXDLLIMPEXP_FWD_BASE wxMessageOutput;

#if wxUSE_GUI
struct WXDLLIMPEXP_FWD_CORE wxVideoMode;
class WXDLLIMPEXP_FWD_CORE wxWindow;
#endif

// this macro should be used in any main() or equivalent functions defined in wx
#define wxDISABLE_DEBUG_SUPPORT() \
wxDISABLE_ASSERTS_IN_RELEASE_BUILD(); \
wxDISABLE_DEBUG_LOGGING_IN_RELEASE_BUILD()

// ----------------------------------------------------------------------------
// typedefs
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -772,8 +777,13 @@ class WXDLLIMPEXP_BASE wxAppInitializer
// your compiler really, really wants main() to be in your main program (e.g.
// hello.cpp). Now IMPLEMENT_APP should add this code if required.

#define IMPLEMENT_WXWIN_MAIN_CONSOLE \
int main(int argc, char **argv) { return wxEntry(argc, argv); }
#define IMPLEMENT_WXWIN_MAIN_CONSOLE \
int main(int argc, char **argv) \
{ \
wxDISABLE_DEBUG_SUPPORT(); \
\
return wxEntry(argc, argv); \
}

// port-specific header could have defined it already in some special way
#ifndef IMPLEMENT_WXWIN_MAIN
Expand Down
10 changes: 2 additions & 8 deletions include/wx/build.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "wx/version.h"

// NB: This file contains macros for checking binary compatibility of libraries
// in multilib buildm, plugins and user components.
// in multilib builds, plugins and user components.
// The WX_BUILD_OPTIONS_SIGNATURE macro expands into string that should
// uniquely identify binary compatible builds: i.e. if two builds of the
// library are binary compatible, their signature string should be the
Expand All @@ -42,12 +42,6 @@
__WX_BO_STRINGIZE(x) "." __WX_BO_STRINGIZE(y) "." __WX_BO_STRINGIZE(z)
#endif

#ifdef __WXDEBUG__
#define __WX_BO_DEBUG "debug"
#else
#define __WX_BO_DEBUG "no debug"
#endif

#if wxUSE_UNICODE_UTF8
#define __WX_BO_UNICODE "UTF-8"
#elif wxUSE_UNICODE_WCHAR
Expand Down Expand Up @@ -100,7 +94,7 @@
// This macro is passed as argument to wxConsoleApp::CheckBuildOptions()
#define WX_BUILD_OPTIONS_SIGNATURE \
__WX_BO_VERSION(wxMAJOR_VERSION, wxMINOR_VERSION, wxRELEASE_NUMBER) \
" (" __WX_BO_DEBUG "," __WX_BO_UNICODE \
" (" __WX_BO_UNICODE \
__WX_BO_COMPILER \
__WX_BO_STL \
__WX_BO_WXWIN_COMPAT_2_6 __WX_BO_WXWIN_COMPAT_2_8 \
Expand Down
Loading

0 comments on commit 7d9550d

Please sign in to comment.