Why does catching C++ bad_cast not work?

I'm on FreeBSD 9.1. Consider the following code:
Code:
#include <exception>
#include <typeinfo>
#include <stdio.h>

class foo {
public:
    virtual ~foo() {}
};

class bar: public foo {
public:
    int val;
    bar(): val(123) {}
};

static void
cast_test(const foo &f) {
    try {
        const bar &b = dynamic_cast<const bar &>(f);
        printf("%d\n", b.val);
    } catch (const std::bad_cast &) {
        printf("bad cast\n");
    }
}

int main() {
    foo f;
    cast_test(f);
    return 0;
}

On FreeBSD:
Code:
$ g++ badcast.cpp -o badcast -Wall && ./badcast
terminate called after throwing an instance of 'std::bad_cast'
  what():  std::bad_cast
Abort trap (core dumped)

$ g++ badcast.cpp -o badcast -frtti -fexceptions -Wall && ./badcast
terminate called after throwing an instance of 'std::bad_cast'
  what():  std::bad_cast
Abort trap (core dumped)

$ gcc -v
Using built-in specs.
Target: amd64-undermydesk-freebsd
Configured with: FreeBSD/amd64 system compiler
Thread model: posix
gcc version 4.2.1 20070831 patched [FreeBSD]

$ uname -a
FreeBSD freebsd9 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243825: Tue Dec  4 09:23:10 UTC 2012     
root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  amd64

On Debian Linux 6:
Code:
$ g++ badcast.cpp -o badcast -Wall && ./badcast
bad cast

On OS X 10.8:
Code:
$ g++ badcast.cpp -o badcast -Wall && ./badcast
bad cast

Why does catching bad_cast not work on FreeBSD?
 
That's certainly strange. I originally thought it was a bug in GCC 4.2, but it affects clang and GCC 4.6 also.

Maybe you should file a ticket.
 
I think the ticket should be classed critical with priority high. It's a fundamental feature of the C++ language that should never have problems.
 
nslay said:
I think the ticket should be classed critical with priority high.

It sounds like you're saying that you think everybody doing anything on FreeBSD should stop what they're doing and work on this problem that annoys you. Good luck with that.
 
Uniballer said:
It sounds like you're saying that you think everybody doing anything on FreeBSD should stop what they're doing and work on this problem that annoys you. Good luck with that.

No, that's not what I'm saying at all. I'm saying that there are thousands of ports written in C++ and several utilities in the source tree written in C++ that rely on standard language behavior (such as catching exceptions!).

It's not a just mere annoyance ... it's a serious problem that potentially affects any C++ application running on FreeBSD.
 
No, this is a real problem that must be solved somehow. Catching exceptions must work, how else can you claim that the implementation is standards conforming?
 
My guess is that unless somebody makes it their pet project it won't get done. For example, the terminal driver is no longer POSIX compliant as of 8.0 due to issues with tcdrain(3). This problem broke standards compliant working code. Multiple SPRs have been written (including one by phk) pointing this out, but no action has been taken. It appears that because essentially nothing in the base code depends on this feature nobody cares to work on the problem.
 
Sigh, I'm amazed that people can say things like that.

This isn't a small thing that's broken. This is one of the *most fundamental* C++ language properties being broken. It's almost like "rm -f" not working anymore.

The Phusion Passenger web application server depends on this feature. Break dynamic_cast, and you break a majority of the Ruby web apps out there. I discovered this bug while testing Phusion Passenger on FreeBSD 9.1.
 
This seems to have worked in the past. It fails on i386 and amd64 under 9.1, but seems to work on i386 under 8.3.

Did it work on 9.0?
 
Back
Top