Fun with C++: Function Try Blocks

C++ is complex. That might sound like an about right to two groups of people – those who don’t know C++ and those who really know C++ – but only those who really know understand the depth of that statement. I’m only beginning to learn C++ and I’m only just learning the depth of it.

Take the following sample code for instance:

1
2
3
4
5
6
void foo ()
try {
    // Some code
} catch (...) {
    // More code
}

As surprising as this might be to some (or not) the above is a valid C++ function definition. That’s right. No regular body in this function.
Now, the skeptics among you might wonder what usefulness this might possibly have! Wonder no longer. The foremost use (and the most straightforward one) is in the context of constructors and correct exception handling.

Suppose you have the following class and constructor:

1
2
3
4
5
6
7
8
9
10
11
12
struct Bar
{
    Bar ();
 
    // Baz is another class that might throw an exception in its c'tor.
    Baz m_baz;
};
 
Bar::Bar ()
    : m_baz ()
{
}

How can you handle exceptions that might be thrown when m_baz is being constructed (e.g to do something useful with them?)
The answer is obviously a try body for the constructor. A la:

1
2
3
4
5
6
7
Bar::Bar ()
try
    : m_baz ()  // Note the "interesting" placement!
{
} catch (std::exception & e) {
    std::cerr << "'Bar' c'tor is FUBAR!" << std::endl;
}

This has other very cool usages too. For example, to define a macro, with an aesthetically pleasing usage, to track entry into any function (for run-time call graph generation and other analyses.)

1
2
3
4
5
6
7
8
9
10
11
12
#define TRACK_FN                                 \
    try {                                        \
        GlobalFunctionTracker::onFuctionEntry    \
            (__FUNCTION__, __FILE__, __LINE__);  \
        throw (42);                              \
    } catch (int)
 
// Use the above macro like this
void qux (int arg) TRACK_FN
{
    // Do your thang here...
}

Of course, this is not the most efficient way to implement this, but its the most beautiful one!
Some notes:

  1. In effect, we are injecting code into the scope of the function. All the function arguments are available in the try and catch blocks.
  2. If you use this try-block thingy for a constructor or destructor, the exceptions thrown in the try block will propagate automatically beyond the local catch! For all other kinds of functions, this will not happen and if you catch the exception, it will be stifled unless you rethrow it explicitly.
VN:F [1.9.13_1145]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.13_1145]
Rating: 0 (from 0 votes)
Fun with C++: Function Try Blocks, 10.0 out of 10 based on 2 ratings

13 Comments

  1. MatGill says:

    I suppose this goes the same for calling a base constructor from the inherited class. Now I’m beginning to understand why Java pushed that inside the method itself. More language consistency I guess.

    VA:F [1.9.13_1145]
    Rating: 1.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  2. Of course, more language consistency, plus more overhead and less performance and a metric ton of less coolness!

    VA:F [1.9.13_1145]
    Rating: 5.0/5 (2 votes cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  3. MatGill says:

    What does Java’s syntax calling the base constructor vs C++’s initialization list cause overhead? Wouldn’t have it been better if C++ called base constructor (or member constructors) at the first line of the constructor so that the try/catch could be used in its normal form?

    Loving a language is something, but being stubborn about it is totally different. In fact, a large subsection of Java can be compiled into efficient programs. You would only get considerable overhead if you start using the highly dynamic features of the language. Syntax-wise, however, Java is far better designed that C++. It is almost impossible for the “mid class” programmer to master C++ because of all these exceptions and syntax inconsistencies. There are millions of ways to do even simple things in C++ and each of which has its own story. I’d rather cut down on many of the stupid syntax and use a subset of the language that is more consistent and can get the work done seamlessly and elegantly (the latter is more important to me).

    Leonard Cohen live in London is now playing on CBC. Great stuff man, great stuff.

    VA:F [1.9.13_1145]
    Rating: 1.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  4. Hamid says:

    @MatGill
    “a large subsection of Java can be compiled into efficient programs. You would only get considerable overhead if you start using the highly dynamic features of the language.”

    I think the main reason for Java’s overhead is somehow intrinsic into the language. That is, Java forces you to allocate everything dynamically and as a consequence produce a lot of garbage. For example consider this statement A a = new A()
    Its C version is: struct A *a = malloc(sizeof(A))

    However, there is no way to do that like this: struct A a

    Yet, as another point, In Java, there is no way to dereference pointers explicitly. You only dereference pointers through 2 kinds of statements: Field Loads and Field Stores.

    Field Load like: v = a.f C version: v = (*a).f
    Field Store like: a.f = v C version: (*a).f = v
    These things may introduce unnecessary pointer dereferences. Hopefully, they can be eliminated by the compiler.

    There is no way to do something like this: a = &my_stack_allocated_object
    You get the point, there is no way to allocate any object (except primitives and the pointers themselves which are not objects) from the stack. However, with some analysis like Side-effect-Analysis, it is possible to do so even in Java (not explicitly by the programmer but through compiler optimizations)

    VA:F [1.9.13_1145]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  5. MatGill says:

    Let me emphasize on the the word “considerable” once again. Of course you’ll get some overhead for not using stack structures and dereferencing you objects. Though I don’t think of this as a bad idea, but rather a wise design issue. If you write your code truly object oriented in C++ you will never have to allocate structs on the stack (or any other group of objects). The only objects on the stack will be primitives and the rest will be in the heap (I’d suggest you go and check out your own pure object oriented C++ code and check this out, at least this was the case for my code). At any rate, this type of memory access is not that bad as it will mainly be using CPU’s cache (stack gets into cache with the memory address in it). In fact if you properly use encapsulation in Java you’ll almost never see this accessing/dereferencing overhead (vaguely recalling some empirical studies, etc).

    VA:F [1.9.13_1145]
    Rating: 1.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  6. Hamid says:

    I agree with you on most of the points. However, I think the price of Garbage collection can get considerable. That’s why Java’s compilers tries to find objects local to some function (objects which are allocated within the scope of the function and read and written only within that function) and allocate them from stack (or some heap local to function).

    And, that’s why there is so much effort to port Java applications to embedded systems (to the extent I know)

    VA:F [1.9.13_1145]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  7. MatGill says:

    @Hamid: I’m totally with you on the problem with the garbage collection in Java. But I was not arguing about all the design issues, but specifically Java’s syntax. My point was that Java made a great move towards a simpler and more consistent syntax. There are clones of the language that try to get better with the performance by freeing up the memory explicitly, but keeping all the rest the way it is. This way you can compile a big subset of the language into machine code (this was what I was talking about in my first comment). You can also do it the easier way and try to use a subset of C++ that is clean and consistent. You do _not_ need to master C++ to write elegant code in it.

    VA:F [1.9.13_1145]
    Rating: 1.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  8. yzt says:

    @MatGill(3):
    First, let me describe my view on why Java introduces overhead in this case and why C++ cannot use Java’s syntax and ultimately why C++’s syntax is better.

    As our friend Hamid said, all objects in Java are heap-allocated using the “new” keyword (obviously.) If you don’t new your member objects in the constructor of a class, you have null references. This means that your references are already initialized to null. There goes your first overhead. You cannot prevent the runtime from setting all member data to null (forget about primitive types for now.) You will no doubt object that this is not a big overhead but that doesn’t change anything. This is an overhead that you cannot prevent in any way. And this is just one of maaaaaaaany.

    Also, C++ is a multi-inheritance language and Java is not. Regardless of what you think about single vs. multiple inheritance, this means that you cannot use the single keyword “super” eaither. Also, C++ strives to make all reasonably written C programs also valid C++ programs, which makes introducing new keywords very dangerous, specially keywords with such a commonly-used name and keywords that can be used inside a function body.
    Besides, what’s the syntactic advantage of forcing people to write something on the first line of a constructor and introduce a new keyword, over forcing them to write it before the first line with some added punctuation?

    Java might have a better syntax than C++, but that’s hardly a great achievment for them. Almost anybody can design a perfect language syntax if it weren’t for the users! If C++ needn’t be compatible with C, almost none of what people perceive as flaws and much of its complexity would disappear, but almost nobody would have used it in the 80s, and it would have certainly died out by now.
    Java designers didn’t have the requirement to be able to compile C or C++ programs as valid Java programs and still they borrowed much of the syntax.

    Frankly, I didn’t expect this level of naiveness from you. I did not even mention Java in my post and the statement I made about Java’s performance overhead is obviously and trivially justifiable. Yet you accuse me of stubbornness and blindly supporting my language?!

    Granted, there are many more dark corners and “advanced” features in C++, but that’s simlply because C++ has more features and does more. There is a saying about programming languages: a good programming language should make common stuff easy and uncommon stuff possible. There is very little that is impossible in C++ (think boot loaders and Interrupt Service Routines) which is why I love it. Also, it makes all this possible without any unwanted overhead. You only pay for the features that you use (exception handling, runtime type information, etc.) Can that be said of any other language at a higher level?

    Anyway, I am a (hopefully) game developer. My taste and preferences is obviously leaning towards performance.

    VN:F [1.9.13_1145]
    Rating: 5.0/5 (1 vote cast)
    VN:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  9. random dude says:

    سلام کسی اینجا پروژه دانشجویی مینویسه؟
    یه برنامه میخوام که لیست یه سری دانشجو رو بگیره و معدلشون رو چاپ کنه
    توروخدا فقط زود بهم میل کنین به خودا این طرم مشروت میشم بخدا

    VA:F [1.9.13_1145]
    Rating: 5.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  10. MatGill says:

    @yzt: Well, there seems to be a bit of miscommunication going on in here (probably on my side). I was saying that they had a good reason in Java to move things inside the constructor to make the syntax more consistent and you said that it adds some overhead, where as arguably it will not (you probably thought of the whole language). I was not at all talking about the language as a whole (neither about C++ nor Java), but rather this specific syntax design choice. The design of C++, just like any other language, has its own flaws, not all of which is due to backwards compatibility issues. I do see this unusual try catch syntax as a design flaw and not a cool unknown geeky fact. I also see this as a form of stubbornness on your behalf as your immediate response to such claim is that the mere idea of pushing init list to the method body will cause overhead! (or maybe as I said just a miscommunication here) I’m sure they could have come up with a better designs even with the multiple inheritance issues. They could have overloaded keywords (just like they did with maaaaaaaaaaaaaaaany other cases when it came to backwards compatibility, now I did not think you could be so naive about this ;) just joking).

    At any rate the init list and try catch block are two orthogonal features of C++ that have clashed badly on this particular case (caused an exception in the syntax). I don’t like this, you might love it. In matters of taste there is no dispute my friend. And yes, you can be stubborn about your taste.

    On the issue with Java’s overhead for exclusively using the heap , as I said, you are absolutely right. Yet I don’t see that as a “considerable” overhead not because it’s tiny, but because my own C++ codes use the heap space exclusively. I think that’s the correct way to write object oriented code (you might call that naive or whatever, but in my (previous) line of work a clean code was much more preferred to a faster one). Now you could say I need better performance, and I would say, well, Java is not designed for that and OO programming certainly does not consider performance as a major issue. You should bend the rules to for performance issues and I won’t call you on that.

    C++ does almost everything, but not everyone writes every possible type of program. As I said, in my clean OO world with little performance concerns, I would rather go for a clean subsection of the language that fits the needs. I also love C++, but not for the same reasons you do.

    You are absolutely right about the ease of designing the syntax for Java as they did not need to think about backwards compatibility or, say, many of the issues with destructors. But it does not, at all, mean that C++ was perfect in its design in every aspect, only because the designers’ hands were tight with C. I know you did not mean to say anything like that, but you sounded like you did (miscommunication again), and that’s why I called you on it. No offense dude :D chill out. After all I’m a cheap boy who wears colored contact lenses and bleaches his hair. You can’t possibly take me seriously :D

    VA:F [1.9.13_1145]
    Rating: 1.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  11. @MatGill(General):
    Well, it seems that we should agree to disagree on some matters of taste!
    I do agree with the fact that Java’s syntax is generally cleaner (specially in matters of object oriented programming) but that’s to be expected, because it’s a newer language and they didn’t have to concern themselves with source code compatibility with any other language. Of course, they opted to make it similar to C/C++, but I think it’s hard to find any non-trivial piece of C++ code that compiles as Java or the other way around.

    However, my point is that while Java may be cleaner and more elegant in syntax (in some areas of syntax. Some Java features are not pretty at all!), say 10%-20%, it’s at least 100% slower. And doing some stuff are outright impossible.
    I prefer C++ because it let’s me be exactly as fast as I’m willing to be, and exactly as clear and elegant as I can be. Let’s not forget that C++ has probably more features (even related to OOP) than Java, which again obviously adds to the complexity of the language.

    By the way, I’m curious. If elegance and cleanliness (and while you didn’t mention it, I guess succinctness is important for all of us too) is your foremost concern, why don’t you go and use more elegant languages? Python? Lisp?

    VA:F [1.9.13_1145]
    Rating: 5.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  12. MatGill says:

    I totally agree with you on almost everything you just said. Specially since I managed to make you praise Java’s syntax and call it (in parts) elegant :D

    I still use C++ unless it gets to the point I need to reach outside the computer (sockets, rpc rmi, standardized networking protocols, etc), use threading (lets face it, standard C++ sucks in that) or handle standardized files and protocols (xml files, databases, etc). The reason: I’m too lazy to check out boost, and boost has only recently introduced some ‘usable’ threading functionalities.

    I do use Python extensively :D and I love it. I even did a whole project in python (ten or so thousand lines of OO style python, and you know each line in python is like 10 in Java or C). But I’m afraid these days I’m usually forced to use certain languages. So I use python whenever I can. It’s like smoking in the break time while you have to do a boring 9 to 5 job :D

    VA:F [1.9.13_1145]
    Rating: 1.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)
  13. MatGill says:

    I just noticed somebody has been rating our comments here. Hmmm… interesting. I have never been ranked by a random dude before.

    VA:F [1.9.13_1145]
    Rating: 1.0/5 (1 vote cast)
    VA:F [1.9.13_1145]
    Rating: 0 (from 0 votes)

Leave a Reply