Dont read this blurb! Read this column instead. Its 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 Britains DTI (their equivalent of our FCC):
[Journalists] shouldnt have any interest in Numbers Stations because they shouldnt be listening to them because they are illegal to listen to.
Incrediburgible!
What makes this even more astonishing: you cant know a station is illegal until you hear it, by which point youre already a criminal. And since these stations dont 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. Id really like to know. Meanwhile, Ill 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 doesnt 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 expressionIt 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 dont say what compiler youre using, your diagnostics format strongly suggests Visual C++ v6. As I dont have that compiler installed anymore, I cant verify my assumption; but given that compilers anemic template support, the result youre getting sounds right.
Ill add two more observations.
First, you can rewrite:
f<X>(this)as:
f(this)The function calls argument type (X*) forces the implicit instantiation of function f<X>(X*) to match. Microsofts 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 dont know if this is a demonstrative example only, or part of a more serious design, I cant 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 its 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
Im treating your question as if it were really two:
- How can you learn an exceptions context, specifically location and stack frame?
- What can you know from catch (...)?
Answer #1:
What youre 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 compilers 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:
- That an exception of some type was caught.
- That the exception isnt of a type catchable in any previously tried handlers.
For example, at the indicated point in:
try { // exception thrown... } catch (std::exception) { } catch (int) { } catch (...) { // ...and caught here }you know that:
- Some exception was caught.
- The exception is not type std::exception or derived from std::exception.
- The exception is not type int.
Otherwise, you know nothing, including the exceptions actual type. You dont even have a name for the exception, or a void * or similar typeless handle to the exception.
In practical effect, you arent 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 customers 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 // ... #endifCan 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 Bare exactly equivalent to:
#if defined A #if !defined BYou can combine defined with other expressions to form more complex conditional inclusion:
#if (defined A || B > 1) && !CIn your case, the correct combination is:
#if defined A || defined B || defined C // ... #elif defined D || defined E // ... #else // ... #endifdefined 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 dont 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 thats 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->iwere 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 todays winner! I do believe you are correct. Im a little dismayed I didnt find and follow that trail myself, but hey! Thats why we have Diligent Readers on the payroll.
Notes
[1] <www.ibmpcug.co.uk/~irdial/conet.htm>
[2] Lest you think Im picking on the British government: I see many parallels here with our own governments 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: Microsofts .NET Framework lets you gather such information for exceptions in managed C++ code.
[6] Before you get excited, Dr. Meyers, note that technically Im 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.