lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi] NDEBUG [Was: PDF opening errors]


From: Greg Chicares
Subject: [lmi] NDEBUG [Was: PDF opening errors]
Date: Thu, 23 Oct 2014 12:39:54 +0000
User-agent: Mozilla/5.0 (Windows NT 5.1; rv:24.0) Gecko/20100101 Thunderbird/24.6.0

On 2014-10-19 19:25Z, Vadim Zeitlin wrote:
> On Sun, 19 Oct 2014 19:00:15 +0000 Greg Chicares <address@hidden> wrote:
> 
> GC> Thanks. On another tangent...why was this message:
> GC> 
> GC> GC> > GC> In file ../src/msw/mimetype.cpp at line 272: 'AssocQueryString' 
> failed with error 0x80070002 (the system cannot find the file specified.).
> GC> 
> GC> displayed only with 'wx_test.exe' and not with './lmi_wx_shared'?
> 
>  Simply because the debug messages are not displayed to the user in message
> boxes by default, i.e. when using wxLogGui which is the default wxLog
> target, but the test code sets up wxLogWindow log target to collect all
> logs in a single place and wxLogWindow dose show all messages, including
> the debug ones.

Good: these messages are also available in the production system,
in case we want to show them there.

> GC> Both use the same wx library, built the same way.
> 
>  I've just realized that this is actually a potential problem. While what I
> wrote above is 100% correct, normally debug messages are not supposed to be
> generated in the first place in the "release" or "production" builds. But,
> as explained at http://docs.wxwidgets.org/trunk/overview_debugging.html, we
> use NDEBUG symbol to determine whether we're building a production version
> and LMI makefiles don't define NDEBUG (configure builds do define it
> though, unless "--enable-debug" option is used). This means that
> wxLogDebug() and wxASSERT() and related macros (wxFAIL, wxCHECK and all
> their versions) remain active in LMI builds which may be not what you want,
> i.e. I think that LMI should, at least optionally, suppress them because
> they are normally not meant for the end users at all.

Okay. Maybe I'm missing something, but I don't see this as a problem.

AFAIK, the typical dichotomy is:
 - "release" builds:   optimized;   no debug symbols; NDEBUG defined
 - "debug" builds: not optimized; full debug symbols; NDEBUG not defined
and the idea is that developers work with the latter, but ship the former.
Instead, I normally build only one way--with optimization and debug
symbols--and don't define NDEBUG, for these reasons:

First and foremost, "release" and "debug" builds often behave differently,
e.g., because "debug" builds tend to zero-initialize pointers that in
"release" builds are random. I deliberately use the same build as end
users to ensure that mine behaves exactly the same as theirs (except for
differences I can't control, such as their OS version).

Debug symbols don't slow the program down. They make binaries larger, but
disk space is cheap. They rarely matter to me, because I hardly ever use
a debugger; but they make backtraces much clearer when something crashes.

The gnu documentation says gdb works with optimization, but works better
without it. I can easily build without optimization if I need gdb to work
"better", but I can't remember ever having occasion to do that.

At least for GUI programs, I believe it's generally inappropriate to
call abort(), or (consequently) to use the standard assert() macro;
so I never define NDEBUG. I actively dislike NDEBUG; for one thing,
this search
  https://www.google.com/search?q=ndebug+odr+violation
yields 121,000 hits; and for another, it can easily cause "debug" and
"release" builds to behave differently.

I do use LMI_ASSERT liberally. By design, it doesn't depend on NDEBUG,
and it doesn't call abort(). Its documentation says it "is appropriate
only for lightweight assertions that should be left in released code";
thus, I often do this sort of thing:
  LMI_ASSERT(p); p->foo();
but I rarely if ever do anything like this in production:
  LMI_ASSERT(fast_risky_function() == slow_safe_function());

(I could of course experimentally verify that these assertions cost
little enough, by rebuilding with
  #define LMI_ASSERT(ignore) ((void)0)
and measuring the cost across a thousand regression-test cases; but I'm
confident that lmi wouldn't run materially faster, so that experiment
doesn't seem worthwhile.)

There are quite a few assertions in lmi:
  /lmi/src/lmi[0]$grep LMI_ASSERT *.?pp | wc -l
  690
but we can't recall seeing any of them fire except in rare cases where
we definitely want the end user to stop and contact us. Similarly, we've
never heard of an end user seeing a wx assertion, and searching this
mailing list for "wxWidgets Debug Alert" finds only six distinct reports
in the last ten years:
  1 in 2014-03 [GUI test only--not production]
  1 in 2011-12 [testing a wx upgrade]
  2 in 2011-06 [testing a wx upgrade]
  1 in 2007-11 [deliberate mischief with a non-production feature]
  1 in 2005-12 [early unit testing of a new wx control]
Those reports were helpful, and that's sufficient reason to leave these
wx assertions enabled always.

I'm quite satisfied with this philosophy and unlikely to change it.

However, there is a pragmatic concern that some libraries depend on
NDEBUG. For example, see the comment beginning on line 29 here:
  
http://svn.savannah.nongnu.org/viewvc/lmi/trunk/expression_template_0_test.cpp?annotate=5994&root=lmi
That one's a plain mistake in boost IMHO--as mistaken as a hypothetical
GUI library that doesn't use color unless NDEBUG is explicitly set.
(That's another reason to dislike NDEBUG--one might wish or need to
define it for one library, but prefer to leave it undefined for another;
but it might not be possible to maintain separate settings, e.g., if the
main program uses features of both libraries that are implemented in
headers.)

As for wx, OTOH, I guess you need to accommodate users who really want
separate "debug" and "release" builds, and think of NDEBUG as the standard
way of choosing between them--say, because they use an IDE that works that
way. Well, okay--the way wx uses NDEBUG accommodates my philosophy too.
I don't want to define NDEBUG, on principle; I don't want wx's internal
diagnostics to be discarded; and wx treats my wishes as consistent, so
I'm satisfied.

You mentioned that wxLogDebug(), wxASSERT(), wxFAIL, wxCHECK, etc. are
not really meant for end users. Here, I would prefer to leave well
enough alone: in practice, they never see this stuff; and if they ever
do, I'd like them to tell us. These facilities have on occasion helped
our testing. We certainly don't want to test two different builds of
the same wx release.

Is there any other reason to change anything? The size of the library
doesn't really matter. I don't imagine it'll run materially faster
with the debugging macros disabled. I'm leaning toward the conclusion
is that the way wx uses NDEBUG gives me exactly what I want for lmi.

But...what about this
  http://lists.nongnu.org/archive/html/lmi/2007-11/msg00004.html
old discussion? I guess the thoughts I expressed there have changed
because I now have more information; and it'll be clearer to address
that in a separate message.

> GC> The reason why I ask is that I'm wondering if there's some way I could
> GC> (optionally) enable messages like this in the production system (say,
> GC> only with a special command-line argument).
> 
>  Yes, the nice thing about wxWidgets 3.0 debug/release mode handling is
> that it all happens during run-time: unless you went out of your way to
> build wxWidgets without any debugging at all (i.e. configured it with
> --disable-debug), the code of wxLogDebug() and assertion macros is always
> compiled in and just remains dormant by default if NDEBUG is defined.
> 
>  As mentioned above, in LMI case it's not even dormant because, first,
> NDEBUG is never defined and, second, because LMI doesn't use
> wxIMPLEMENT_APP() which deactivates all this debugging stuff if NDEBUG is
> defined (this is not part of IMPLEMENT_APP_NO_MAIN() used by LMI).

Technically, it's not even dormant; but practically, it's invisible.
To our knowledge, no end user has ever seen any manifestation of it.
We observe it perhaps a few times in a decade, generally when we're
testing a new wx feature or a new wx release. And when we do notice it,
it identifies a previously unnoticed problem that then gets fixed soon
after we mention it here.

Do you suppose we'd get a noteworthy improvement in runtime performance
if we deactivated it? I'm guessing that it's probably not even worth the
time to try, and I'm not sure how we'd measure it anyway.

>  The least intrusive way to do what you want would probably be to do this
> deactivation ourselves in main_wx.cpp. If you decide to define NDEBUG, this
> would be as simple as adding a call to wxDISABLE_DEBUG_SUPPORT(). If not,
> you can still do it by manually doing what this macro does when NDEBUG is
> defined, namely:
> 
>       wxDisableAsserts();
>       wxLog::SetLogLevel(wxLOG_Info);

Unless I'm missing something, the effect would be to block exceedingly
rare diagnostics that we would rather see.

>  Please let me know if you have any more questions and whether you'd like
> me to make a patch doing the above. To be honest, I think it would be
> simpler if you just addressed it yourself though, as the change itself is
> trivial, the less obvious part is determining whether you want NDEBUG to be
> defined or not (I think you should but you may think differently) and how
> do you want to control wx debugging diagnostics (I think they should be off
> by default and an option such as "--debug" should be provided to enable
> them).

It's been interesting to learn more about this, but the only thing I'm
motivated to pursue is to enable more diagnostics optionally. This
message is long enough already, so I'll address that separately.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]