exceptions disabled - Clang

3,340 views
Skip to first unread message

Max Suster

unread,
Nov 30, 2014, 5:59:12 PM11/30/14
to julia...@googlegroups.com
Hi

I am not very familiar with the mechanics of exception handling in Clang and I realize that exceptions (throw/catch) work well in Julia itself. However, I am specifically trying to use exception handling in C++ code nested inside Julia with Cxx.jl. I noticed exception handling is meant to be switched off by default in Clang, but still it seems to me that it would be very useful to have it switched on when dealing with GUI applications.

I tried several C++ exceptions (e.g., throw/catch, std::exception) but it seems they are disabled in my current Julia-v0.4.0-dev build (OSX 10.9.5). Since I did not use the -fno-exceptions flag to build Julia, I wonder why/where exceptions are switched off when I built Julia.

In Xcode(with libc++-LLVM, C++11), I can run the following script with C++ exceptions and it works:

const int ZeroDivisionError = 1;
double divide(double x, double y)
{
      if(y==0)
      {  
           throw ZeroDivisionError;
      }
      return x/y;
}

int main()
{
      try
      {
           divide(1, 0);
      }
      catch(int i)
      {
            if(i==ZeroDivisionError)
            {
                  std::cerr<<"Divide by zero error";
            }
      }
}

Divide by zero error Program ended with exit code: 0

However, when I try to compile essentially the same code in Julia (with Cxx), I see the following ERROR:

julia> cxx"""
#include <iostream> //std::cerr
const int ZeroDivisionError = 1;
double divide(double x, double y) 

      if(y==0) 
      {  
           throw ZeroDivisionError; 
      } 
      return x/y; 


void exceptiontest() 

      try 
      { 
           divide(1, 0); 
      } 
      catch(int i) 
      { 
            if(i==ZeroDivisionError) 
            { 
                  std::cerr<<"Divide by zero error"; 
            } 
      } 
}

In file included from :1: 

:9:25: error: cannot use 'throw' with exceptions disabled
throw ZeroDivisionError;
^
:16:20: error: cannot use 'try' with exceptions disabled
try
^

Does anyone know how I can switch on exception handling in Clang for building Julia?
Alternatively, if the exception flag is already included by default, then at least I know to focus on why it is not being used by Cxx.

Thank you for your time. 

Max

Keno Fischer

unread,
Nov 30, 2014, 6:18:41 PM11/30/14
to julia...@googlegroups.com
This is primarily a Cxx.jl issue, though you might run into problem if you're trying to unwind through non-C++ frames later. In any case, in the spirit of experimentation, you can enable exception handling by setting the appropriate options from here:

in bootstrap.cpp, e.g. here:

ele...@gmail.com

unread,
Nov 30, 2014, 7:43:09 PM11/30/14
to julia...@googlegroups.com


On Monday, December 1, 2014 9:18:41 AM UTC+10, Keno Fischer wrote:
This is primarily a Cxx.jl issue, though you might run into problem if you're trying to unwind through non-C++ frames later.

To amplify, Julia uses lots of libraries that are not guaranteed to be exception safe, and can leak resources or leave memory in unknown and/or illegal states when you throw exceptions through them.  If your exceptions are only used to terminate the process thats mostly fine since most resources (memory, open files) are returned on process terminate anyway and the state of memory doesn't matter.  But if you catch the exceptions after they have unwound through non-c++ code and then you try to continue, you could run into problems with leaks or data structures in indeterminate states. Caveat Emptor :)

Cheers
Lex

Max Suster

unread,
Nov 30, 2014, 9:10:13 PM11/30/14
to julia...@googlegroups.com
Thanks for the quick feedback.  

I managed to get C++ exception handling working in Cxx, after some back and forth experimentation.
In the end, I added the following to bootstrap.cpp:

// Enable C++ exception handling
clang_compiler->getLangOpts().Exceptions = 1;          // exception handling
clang_compiler->getLangOpts().ObjCExceptions = 1;  //  Objective-C exceptions
clang_compiler->getLangOpts().CXXExceptions = 1;   // C++ exceptions


However, note that you may NOT add SjLjExceptions at least on OSX (at least not without further changes):
clang_compiler->getLangOpts().SjLjExceptions = 1;    // setjmp-longjump exception handling

The latter produced the following ERROR after using a simple "throw" test code (see below):
LLVM ERROR: Program used external function '___gxx_personality_sj0' which could not be resolved! 

I then rebuilt libcxxffi.dylib with Pkg.build("Cxx") and tested the same zeroDivExceptionTest C++ script:

julia> cxx"""
    
    #include <iostream> //std::cerr 
    const int ZeroDivisionError = 1;
    
    double divide(double x, double y) 
    { 
          if(y==0) 
          {  
               throw ZeroDivisionError; 
          } 
          return x/y; 
    } 

    void zeroDivExceptionTest(double a, double b) 
    { 
          try 
          { 
               double c = divide(a, b); 
               std::cout<<"Result is: " << c <<std::endl; 
          } 
          catch(int i) 
          { 
                if(i==ZeroDivisionError) 
                { 
                      std::cerr<< "Divide by zero error!" <<std::endl; 
                } 
          } 
    }
"""

julia> @cxx zeroDivExceptionTest(5.0, 0) 
Divide by zero error! 

julia> @cxx zeroDivExceptionTest(1.0, 5.0)
Result is: 0.2 

julia> @cxx zeroDivExceptionTest(43.3, 0)
Divide by zero error!

Max Suster

unread,
Dec 1, 2014, 10:37:48 AM12/1/14
to julia...@googlegroups.com

Keno - I got a little ahead of myself with my last post.   While exception handling works fine in several examples, after adding the lines to bootstrap.cpp,  I now get a nasty error from Clang  when using OpenCV functions that require casting with RTTI (i.e., dyne_cast) . Such OpenCV functions worked before adding the exception handling flags to bootstrap.cpp.

e.g., 
julia> img = imread(filename)     # => here it must convert a const char* to const String&
Assertion failed: ((Flags & RF_IgnoreMissingEntries) && "Referenced value not in value map!"), function RemapInstruction, file /Users/maximilianosuster/julia-v0.4.0/deps/llvm-svn/lib/Transforms/Utils/ValueMapper.cpp, line 194.

The error can be eliminated by commenting out the following line (and not the others):
clang_compiler->getLangOpts().Exceptions  = 1;     // exception handling

This is the function that the error refers to in Transforms/Utils/ValueMapper.cpp

void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap,
                            RemapFlags Flags) {
  // Remap operands.
  for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) {
    Value *V = MapValue(*op, VMap, Flags);
    // If we aren't ignoring missing entries, assert that something happened.
    if (V != 0)
      *op = V;
    else
      assert((Flags & RF_IgnoreMissingEntries) &&
             "Referenced value not in value map!");
  }

I tried to understand what is going on, but AFAIK Clang has its own built-in RTTI and its not entirely clear to me why switching on exceptions in bootstrap.cpp compromises the casting of const char* to String& reference.  I tried enabling RTTI =1 and RTTIData = 1 in bootstrap.cpp and removed the -fno-rtti flag from the BuildBootsrap.Makefile. This generated a fatal ERROR upon Pkg.build("Cxx").

Any thoughts on what is going on?  


Lex thanks for the tip on the use of exceptions.  The immediate aim is to simply avoid crashing the julia REPL every time Clang does not like something in the C++ function arguments.  I would prefer eventually to transfer most error checking/exception handling to Julia, but there are cases where some algorithms are best executed in C++.
   

ele...@gmail.com

unread,
Dec 1, 2014, 6:56:30 PM12/1/14
to julia...@googlegroups.com


On Tuesday, December 2, 2014 1:37:48 AM UTC+10, Max Suster wrote:

Keno - I got a little ahead of myself with my last post.   While exception handling works fine in several examples, after adding the lines to bootstrap.cpp,  I now get a nasty error from Clang  when using OpenCV functions that require casting with RTTI (i.e., dyne_cast) . Such OpenCV functions worked before adding the exception handling flags to bootstrap.cpp.

e.g., 
julia> img = imread(filename)     # => here it must convert a const char* to const String&
Assertion failed: ((Flags & RF_IgnoreMissingEntries) && "Referenced value not in value map!"), function RemapInstruction, file /Users/maximilianosuster/julia-v0.4.0/deps/llvm-svn/lib/Transforms/Utils/ValueMapper.cpp, line 194.

The error can be eliminated by commenting out the following line (and not the others):
clang_compiler->getLangOpts().Exceptions  = 1;     // exception handling

This is the function that the error refers to in Transforms/Utils/ValueMapper.cpp

void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap,
                            RemapFlags Flags) {
  // Remap operands.
  for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) {
    Value *V = MapValue(*op, VMap, Flags);
    // If we aren't ignoring missing entries, assert that something happened.
    if (V != 0)
      *op = V;
    else
      assert((Flags & RF_IgnoreMissingEntries) &&
             "Referenced value not in value map!");
  }

I tried to understand what is going on, but AFAIK Clang has its own built-in RTTI and its not entirely clear to me why switching on exceptions in bootstrap.cpp compromises the casting of const char* to String& reference.  I tried enabling RTTI =1 and RTTIData = 1 in bootstrap.cpp and removed the -fno-rtti flag from the BuildBootsrap.Makefile. This generated a fatal ERROR upon Pkg.build("Cxx").

Any thoughts on what is going on?  


Without knowing the context where the map is created and modified, is it possible that a previous caught exception has left the map in a questionable state or failed to add an entry when it terminated some function that wasn't expecting exceptions? 


Lex thanks for the tip on the use of exceptions.  The immediate aim is to simply avoid crashing the julia REPL every time Clang does not like something in the C++ function arguments.  I would prefer eventually to transfer most error checking/exception handling to Julia, but there are cases where some algorithms are best executed in C++.

Sure, using C++ is necessary for now, just don't let the exception escape the C++. 

Max Suster

unread,
Dec 1, 2014, 9:13:19 PM12/1/14
to julia...@googlegroups.com
Without knowing the context where the map is created and modified, is it possible that a previous caught exception has left the map in a questionable state or failed to add an entry when it terminated some function that wasn't expecting exceptions? 


Thanks for the feedback.  Actually, it turns out that the problem is definitely linked to including this line in bootstrap.cpp

    // clang_compiler->getLangOpts().Exceptions  = 1;    // exception handling

What I experience now is that exceptions are only partially detected (not surprisingly after commenting out this line). 
However, at least all other C++ functions are working again.   For example the following 

cxx"""
#include <iostream> //std::cerr

     double divide(double x, double y)
     {
           double z = x/y;
           return z;
     }

     void zeroDivExceptionTest(double a, double b)
     {
           try
           {
               double c = divide(a, b);
               std::cout<<"Result is: " << c <<std::endl;
           }
           catch(...)
           {
               std::cerr<< "Divide by zero error!" <<std::endl;
           }
     }
"""

julia> @cxx zeroDivExceptionTest(10.5, 5.5)
Result is: 1.90909 

julia> @cxx zeroDivExceptionTest(10.5, 0)
Result is: inf

The exception is not caught (no error message), but at least the program does not crash with zero division. 
This is clearly not good enough long-term, but ok for now.

Reply all
Reply to author
Forward
0 new messages