Skip to content

Support for building with exceptions disabled - #1146

Open
twestenkarl wants to merge 3 commits into
jbeder:masterfrom
twestenkarl:master
Open

Support for building with exceptions disabled#1146
twestenkarl wants to merge 3 commits into
jbeder:masterfrom
twestenkarl:master

Conversation

@twestenkarl

@twestenkarl twestenkarl commented Oct 21, 2022

Copy link
Copy Markdown

There are currently three issues for supporting compilation without exceptions
resolves #196 (closed with no changes)
resolves #799 (open, no interaction)
resolves #930 (open, no interaction)

these issue mention the following use case:
using the library for a project where external constraints force it to build without exceptions (e.g. game development, embedded)

My use case is a C++ application that I compile with exceptions enabled for Linux/Windows but also with emscripten for WebAssembly where I disable exceptions.

  1. A new macro YAML_CPP_NORETURN to annotate functions as not returning in dll.h
  2. A new function YAML_throw<ExceptionType>(args...) in exception.h
    this function will throw an exception unless exceptions are disabled in the compiler,
    detected by checking the pre-defined macro __cpp_exceptions
    In this case the exception class will be instantiated, and the user-provided function
    YAML::handle_exception(const char*) will be called on the exception's what() method
  3. if exceptions are disabled,and the library's user does not provide YAML::handle_exception,
    there will be a linker error
  4. all other files have been changed automatedly by running the following sed commands
    sed -i "s/throw \([A-Za-z]*\)(\(.*\))/YAML_throw<\1>(\2)/g" throw statements for non-templated exceptions
    sed -i "s/throw \(.*\)<\(.*\)>(/YAML_throw<\1<\2> >(/g" throw statements for templated exceptions

@twestenkarl

Copy link
Copy Markdown
Author

Notes:

  • this commit does not change the CI config to build with exceptions disabled (which it should add), because I am not familiar with the CI config
  • I tried running clang-format on the source tree, but it would also change files that are unchanged by this commit

@t123yh

t123yh commented Mar 23, 2023

Copy link
Copy Markdown

@t123yh

t123yh commented Mar 23, 2023

Copy link
Copy Markdown

I removed the remaining throws and built it successfully without exceptions.

https://github.com/t123yh/yaml-cpp/commit/12520bd8817077b1b025d810aa135045c73f4893

@SGSSGene

Copy link
Copy Markdown
Collaborator

@jbeder what is your opinion about an "exception free" option for yaml-cpp

@twestenkarl This is a great PR. I do not have a use case for a exception free environment, but this of course doesn't mean other might not have it. If @jbeder sees fit for this, there are two things that this PR still needs:

  1. I think the mechanism should also be shielded by a cmake option, such that we can also use it if __cpp_exceptions evaluates to true.
  2. We need to add the README or Tutorial (or something) that explains this feature.

@jbeder

jbeder commented Aug 11, 2026

Copy link
Copy Markdown
Owner

I suppose it's reasonable, but I never felt like it was worth the readability cost - it seems like it's pretty invasive, since yaml-cpp depends on exceptions pretty heavily for the parsing side of things.

I'd check to see how relevant this still is in 2026 - compilers surely have improved, embedded systems are more powerful, and the last comment here was 2023.

1) A new macro YAML_CPP_NORETURN to annotate functions as not returning in dll.h
2) A new function YAML_throw<ExceptionType>(args...) in exception.h
   this function will throw an exception unless exceptions are disabled in the compiler,
   detected by checking the pre-defined macro __cpp_exceptions
   In this case the exception class will be instantiated, and the user-provided function
   YAML::handle_exception(const char*) will be called on the exception's what() method
3) if exceptions are disabled,and the library's user does not provide YAML::handle_exception,
   there will be a linker error
4) all other files have been changed automatedly by running the following sed commands
   sed -i "s/throw \([A-Za-z]*\)(\(.*\))/YAML_throw<\1>(\2)/g" # throw statements for non-templated exceptions
   sed -i "s/throw \(.*\)<\(.*\)>(/YAML_throw<\1<\2> >(/g" # throw statements for templated exceptions
@SGSSGene
SGSSGene force-pushed the master branch 2 times, most recently from bea8dce to 83ce3e1 Compare August 12, 2026 06:26
- renames the YAML_throw function to raise function
- changes handler from linker decision to runtime variables
- add a second handle_exception_local handler, allowing to handle errors
  in threads locally
- handle exception are always called if available, throwing an exception
  is the default fallback case
- add 'YAML_CPP_USE_EXCEPTIONS' to deactivate throwing exceptions.
- add documentation
@SGSSGene

SGSSGene commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

I'd check to see how relevant this still is in 2026 - compilers surely have improved, embedded systems are more powerful, and the last comment here was 2023.

I also have no clue, I just would like to close all related issues :-).

So I made a huge overhaul of the PR:

  • Changed YAML::Yaml_throw to YAML::raise which makes the calls less noisy:

    throw SomException(param1, param2);       // original
    
    YAML_throw<SomException>(param1, param2); // previous suggestion
    
    raise<SomeException>(param1, param2);     // new suggestion
    

    Now the code for a throw is not much shorter than with raise.

  • I had some worries about testing two version of yaml-cpp with and without exception.
    To combat this, there is a handle_exception handle, which will be called if available. This is independent
    of availability of exceptions or not making this mechanism always available. If someone wants to suppress exception throwing one must set cmake option YAML_CPP_DISABLE_EXCEPTIONS.

  • Because of this new registration mechanism was required, for this 4 new functions are introduced:

    • set_handle_exception, set_handle_exception_local
    • get_handle_exception, get_handle_exception_local

    The difference between the local version is only for the current thread (via thread_local). The other handler
    is a global handler for the complete process. The local handler is always preferred over the global one.
    The set-methods are expecting a function pointer with the signature void my_handler(const char* what) or a nullptr to deactivate them.

  • I also added some documentation to the Tutorial

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants