C/C++ Contributing Editors


Uncaught Exceptions: Don’t Read This Title!

Bobby Schmidt

Don’t read this blurb! Read this column instead. It’s about lifetime, exceptions, and other anomalies. Incredilorious!


Copyright © 2002 Robert H. Schmidt

I recently shared dinner with Doug Payne, a close friend since our days in college radio. Our conversations typically meander in unpredictable and interesting ways. That evening we veered into the topic of “Numbers Stations,” sources of mysterious short-wave broadcasts disavowed by governments and other public agencies.

To a casual listener these broadcasts make no sense. They typically feature voices reading long lists of numbers or letters, Morse code transmissions of same, repeated music, or noise. They are presumably not designed as entertainment. Most expert listeners believe the transmissions to be encrypted messages sent by shadowy government organizations.

That conversational meandering inspired Internet meandering. I eventually tripped upon reviews describing a four-CD set of Numbers Stations’ recordings. Called The Conet Project [1], the set seemed to be out of print. But after a bit of research, I found a U.K. distributor (THESE Records) that had a few copies left. One week and 50£ later, the set was mine.

The fascinating companion booklet illuminates the bureaucratic mind. According to a quoted representative of Britain’s DTI (their equivalent of our FCC):

“[Journalists] shouldn’t have any interest in Numbers Stations because they shouldn’t be listening to them because they are illegal to listen to.”

Incrediburgible!

What makes this even more astonishing: you can’t know a station is illegal until you hear it, by which point you’re already a criminal. And since these stations don’t publish broadcast schedules, every random flip through the short-wave dial risks such illegality.

As I read this, my mind toyed with the boundary conditions. Is it illegal in the U.K. to listen to recordings of these broadcasts? Is it illegal to listen to the recordings themselves being broadcast, instead of an actual live broadcast? Is it illegal for a licensed broadcaster to read the same set of numbers live?

And why are the stations illegal to hear? Because of their content, as if lists of numbers or noises are inherently threatening? Because of their unlicensed state, á la pirate radio? Because of their presumed use as communication in other illegal activity [2]?

If any Diligent Reader from that part of the world knows the answer or rationale, please enlighten me. I’d really like to know. Meanwhile, I’ll continue playing the recordings as an oddly soothing audio wallpaper.

This ’n This

Q

Hi Bobby,

I seem not to understand templates correctly. The following code doesn’t compile:

class X
    {
public:
    X();
    template <class T>
        void f(T *p);
    };

X::X()
    {
    f<X>(this); // error
    }

I always get:

error C2275: 'X' : illegal use
of this type as an expression

It compiles if I declare f global, but then I of course have no access to private members of X (except if I use friend). I hope this is some kind of interesting question, if not, sorry to bother you.

Cheers — Werner Hartinger

A

The fault, dear Werner, is not in yourself, but in your compiler: the above code is correct.

While you don’t say what compiler you’re using, your diagnostic’s format strongly suggests Visual C++ v6. As I don’t have that compiler installed anymore, I can’t verify my assumption; but given that compiler’s anemic template support, the result you’re getting sounds right.

I’ll add two more observations.

First, you can rewrite:

f<X>(this)

as:

f(this)

The function call’s argument type (X*) forces the implicit instantiation of function f<X>(X*) to match. Microsoft’s compiler should accept this construction and thereby solve your immediate problem.

Second, I find the call:

f<X>(this)

suspicious. You are effectively providing the same argument to f<X> twice, as both an implicit this pointer and as an explicit parameter. Since I don’t know if this is a demonstrative example only, or part of a more serious design, I can’t know if this call makes sense.

Space ’n Time

Q

Dear Sir,

I have tested the following code under the Microsoft Visual C++ compiler with service pack 4:

int &f()
    {
    static int slocal = 0;
    return slocal;
    }

f returns the valid address. Is this behavior legal? Does this mean the scope of the local static variable is out of the defining method? Does the ANSI C++ Standard state something about this topic?

Thanks in advance. — David Leal

A

This behavior is allowed and correct.

The issue is not scope but lifetime. Scope is spatial, describing the region over which the name slocal is visible. Lifetime is temporal, describing when slocal is created and destroyed.

slocal is declared within the body of f. Its scope (spatial extent) is therefore limited to the body of f. Within that body, f is visible. Outside that body, it is not.

slocal is also declared with static duration. Its lifetime (temporal extent) starts when it’s initialized — that is, when f is first entered — and ends when the program ends. Any pointers or references to slocal are similarly viable until the program ends.

Had you declared slocal with automatic duration:

int &f()
    {
    int slocal = 0; // not static
    return slocal;
    }

the same analysis would apply, but with very different results. Spatially, slocal is still confined to the body of f. But temporally, slocal is created anew every time f is entered and is destroyed anew every time f is exited. Outside f, pointers and references to slocal are invalid [3], since slocal no longer exists; but again, this is because of lifetime, not scope.

Mystery Date

Q

I am writing a C++ project that uses exception handling. In addition to catching typed exceptions, my software catches untyped exceptions (those caught with catch (...)) in order to gracefully shutdown in the event something extraordinarily bad happens (e.g., an invalid memory access).

It would be nice to have some information to report in a log. Specifically, it would be helpful to get, at the very least, the address where the exception occurred and the cause of the exception. Getting a snapshot of the stack frame at that point would be even better.

Is there a way to get this information within Standard C++?

Thanks. — Dave Stycos

A

I’m treating your question as if it were really two:

Answer #1:

What you’re probably looking for is some Standard C++ library call or object that yields the context of the most recently-thrown exception. Sadly for you, no such standard capability exists for C++ [4].

Depending on your compiler’s non-standard library and your operating environment, there may be proprietary calls you can make to ferret out this information [5]. If so, you may want to package that context within the thrown exception object so that your exceptions become self-describing. It may help to declare your exceptions with a common interface to this information, possibly by deriving from a common abstract base.

Answer #2:

At the point of catch (...), you know only two things:

For example, at the indicated point in:

try
    {
    // exception thrown...
    }
catch (std::exception)
    {
    }
catch (int)
    {
    }
catch (...)
    {
    // ...and caught here
    }

you know that:

Otherwise, you know nothing, including the exception’s actual type. You don’t even have a name for the exception, or a void * or similar typeless “handle” to the exception.

In practical effect, you aren’t catching and handling an exception, but rather you are catching a notification that some exception of some type occurred. The only way to directly make the exception concrete and knowable is to rethrow it and then hope that another handler can grab it by type:

try
    {
    try
        {
        throw x;
        }
    // ...
    catch (...)
        {
        // Anonymous exception of 
        // unknown type. Do something to 
        // note the exception, then 
        // rethrow, hoping another 
        // handler catches it more 
        // precisely.
        throw;
        }
    }
catch (X x)
    {
    // Ah, now the exception has an identity!
    }

As an alternative, you can maintain the state of the last thrown exception and then query that state:

struct
    {
    char const *file;
    char const *line;
    int name;
    // ...
    }
exception_state;

#define THROW(e) \
    do \
        { \
        exception_state.file = __FILE__; \
        exception_state.line = __LINE__; \
        exception_state.name = #e; \
        /* ... */ \
        throw e; \
        } \
    while (false)

// ...

try
    {
    THROW(x);
    }
// ...
catch (...)
    {
    // 'exception_state' contains the
    // state of the last thrown exception.
    }

In the spirit of Answer #1, you can extend this technique to capture non-standard state information such as stack trace, assuming your system yields such information.

Ancient History

Q

Bobby,

I use an enum variable to differentiate among the various configurations of my application that I can produce for different customers. However, my executable has gotten way too big. Since the value of the enum variable is constant for any particular customer’s build, I thought I could just #define the value as a symbol on the compiler command line (Borland C++ Builder 4.x) and then use #ifdef to compile only the code relevant in the build.

This is not working out well at all. What I want is something like:

#ifdef A || B || C
    // ...
#elifdef D || E
    // ...
#else
    // ...
#endif

Can you suggest anything better than:

#ifdef A
    // ...section A
#else
    #ifdef B
        // ...section A repeated
    #else
        #ifdef C
            // ... section A repeated
        #endif
    #endif
#endif
// ...

Thanks in advance — John Billings

A

Your answer requires a simple but woefully underused language feature: the preprocessing unary operator defined.

The two directives:

#ifdef A
#ifndef B

are exactly equivalent to:

#if defined A
#if !defined B

You can combine defined with other expressions to form more complex conditional inclusion:

#if (defined A || B > 1) && !C

In your case, the correct combination is:

#if defined A || defined B || defined C
    // ...
#elif defined D || defined E
    // ...
#else
    // ...
#endif

defined is part of the first ANSI C Standard and is thus over twelve years old. Yet I almost never see header files or other source using it, in production or print. I suspect a lot of programmers are either ignorant of its existence or don’t appreciate its versatility compared to #ifdefs.

I can think of no good technical reason to use #ifdef and #ifndef with modern compilers and related tools. Any Diligent Reader still writing new code with these should immediately cease and desist!

Temporal Anomaly on Europa

Q

I am interested to get an answer from you.

How do I use a combo box, list box, or text box as in Visual Basic using the C or C++ language in my application?

A

Sorry, but that’s not my table.

Spatial Anomaly in Never-Never Land

Q

Dear Sir,

This is not exactly a C/C++ question.

[Rest of question lost in a wormhole.]

A

Remember last month, when I printed what I claimed as my most off-topic post yet? I lied.

Erratica

In my January 2002 column item “When Life Begins,” I proffered that constructs such as:

this->i

were allowable in constructors, even though my literal reading of the Standard suggested such usage led to undefined behavior. To my rescue comes Steve Cleary, Diligent Reader and self-described “lurking language lawyer pupil” [6]:

I agree with everything you say in that article except when you say that the “C++ Standard Subclause 3.8 ... does appear to preclude this in constructors.”

If I may draw your attention to the last sentence of [3.8/3], which redirects you to [12.6.2] and [12.7] for special rules applied during construction and destruction. One of those special rules covers the accessing of nonstatic members (found buried in [12.7/2]).

Thus, I believe that your example of this->i = 7; is perfectly legal and upheld by the current Standard wording.

Steve, you are today’s winner! I do believe you are correct. I’m a little dismayed I didn’t find and follow that trail myself, but hey! That’s why we have Diligent Readers on the payroll.

Notes

[1] <www.ibmpcug.co.uk/~irdial/conet.htm>

[2] Lest you think I’m picking on the British government: I see many parallels here with our own government’s stance on CSS-decryption source code.

[3] Holding a pointer or reference to non-static slocal outside f is “legal” in that the Standard permits such code to compile. However, the resulting program yields undefined behavior.

[4] I can hear the Java partisans in the crowd chortling smugly, since Java programs can portably retrieve much of this information through their analogue of a standard library.

[5] As an example: Microsoft’s .NET Framework lets you gather such information for exceptions in managed C++ code.

[6] Before you get excited, Dr. Meyers, note that technically I’m not the one citing the Standard here!

Although Bobby Schmidt makes most of his living as a writer and content strategist for the Microsoft Developer Network (MSDN), he runs only Apple Macintoshes at home. In previous career incarnations, Bobby has been a pool hall operator, radio DJ, private investigator, and astronomer. You may summon him on the Internet via BobbySchmidt@mac.com.