Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cereal 1.2.0 - “looser throw specifier” error using JSON or XML archive #311

Closed
DaemonPulsar opened this issue Jul 8, 2016 · 11 comments
Labels
Milestone

Comments

@DaemonPulsar
Copy link

also opened on stackoverflow:
http://stackoverflow.com/questions/38267962/cereal-1-2-0-looser-throw-specifier-error-using-json-or-xml-archive

Hello all,

I just moved on Cereal 1.2.0 (moved from 1.1.2), and I obtain a compilation error when using JSONOutputArchive or XMLOutputArchive (i.e. including either "cereal/archives/json.hpp" or "cereal/archives/xml.hpp")

std::stringstream outParamStream;

foo.enable = true;
foo.size = 12;

{
  cereal::JSONOutputArchive outArchive(outParamStream);
  outArchive(foo);
}

doSomeStuffWith(inParamStream->str())

(example is with JSON archive but I have the same behavior using XML archive)

I compile using -std=c++11, with gcc version 4.7.3

Exact errors are :

..sources/ext/cereal/archives/json.hpp:158: error: looser throw specifier for 'virtual cereal::JSONOutputArchive::~JSONOutputArchive()'

..sources/ext/cereal/archives/json.hpp:402: error: looser throw specifier for 'virtual cereal::JSONInputArchive::~JSONInputArchive()'

..sources/ext/cereal/cereal.hpp:584: error: overriding 'virtual cereal::InputArchivecereal::JSONInputArchive::~InputArchive() noexcept (true)'

I do need a std::string so I can't move to binary or portable_binary archive.

Is anyone else experienced this error using Cereal 1.2.0 ?
Did I miss something somewhere ? I did not change my code so I can say basically "it compiles with 1.1.2 and not 1.2.0"

Thanks !

@AzothAmmo
Copy link
Contributor

Can you post the full command you are compiling with? I can't reproduce this with g++-4.7.4 using the following test case, with either XML or JSON:

#include <iostream>
#include <cereal/archives/json.hpp>
#include <cereal/archives/xml.hpp>

struct Window
{
  int height;
  int width;
  bool enable;

  template <class Archive>
  void serialize( Archive & ar )
  {
    ar( CEREAL_NVP(height), CEREAL_NVP(width),
        CEREAL_NVP(enable) );
  }
};

int main()
{
  {
    cereal::XMLOutputArchive ar( std::cout );
    Window w = {101, 200, true};
    ar( cereal::make_nvp("windows", w) );
  }
}

Can you compile the unit tests successfully? When you updated cereal, did you completely remove your old installation?

@erichkeane
Copy link
Contributor

I don't have a local copy of the source right now, but I WILL point out what looks like an error in the code that could have caused this.

Line 258 of cereal/helpers.hpp does this:
virtual ~OutputArchiveBase() CEREAL_NOEXCEPT = default;

HOWEVER, json.hpp line 158 contains:
~JSONOutputArchive()

Seems that CEREAL_NOEXCEPT should be after that as well, since we're inheriting from a virtual destructor.

xml.hpp line 161 has this same problem:
~XMLOutputArchive()

I'm actually REALLY confused though, since the error message refers to InputArchives, yet the code doesn't use them, and there doesn't seem to be any destructors for Json input archive defined. Line 402 (from the error message above) is the class header.

@DaemonPulsar : Can you change json.hpp:158 to be:
~JSONOutputArchive() CEREAL_NOEXCEPT
and see if that changes anything?

@AzothAmmo
Copy link
Contributor

@erichkeane Yeah I noticed that as well - it should probably be changed, though I had the understanding that destructors are implicitly noexcept by default.

@erichkeane
Copy link
Contributor

@AzothAmmo Note that GCC4.7 is horrible for C++11 implementation, so a lot of things like that could likely not be the case in something that old.

@DaemonPulsar
Copy link
Author

I did not have access to my computer this wee-end, but
@AzothAmmo @erichkeane please be assured that I'll try what you ask for as soon as I get it back monday morning.

@erichkeane I don't know a lot about exception mechanism but I tried
json:hpp:158 to be
~JSONOutputArchive() throw()

and it removed the first error.

@erichkeane
Copy link
Contributor

@erichkeane I don't know a lot about exception mechanism but I tried
json:hpp:158 to be
~JSONOutputArchive() throw()
and it removed the first error.

I found this bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 which confirms my suspicion from above, the destructors weren't default-noexcept in the 4.7 branch (though perhaps backported to 4.7.4?).

@DaemonPulsar That would make me think that JSONInputArchive needs the following line added to it:
~JSONInputArchive() CEREAL_NOEXCEPT = default;

@AzothAmmo AzothAmmo added the bug label Jul 8, 2016
@AzothAmmo AzothAmmo added this to the v1.2.1 milestone Jul 8, 2016
@DaemonPulsar
Copy link
Author

ok, so ...
@AzothAmmo
I tried the sample code you provided in your first reply, new empty project.

  • I REMOVED from cereal directory the external/rapidjson/msinttypes/ folder as I use Ubuntu
  • I use Qt
  • gcc 4.7.3
  • compilation command:
    g++ -c -m32 -pipe -Wall -std=c++11 -g -Wall -W -D_REENTRANT -fPIC -D_x86 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -Isources/cereal/.... -o main.o sources/main.cpp

The code you provide fails with:

In file included from sources/main.cpp:25:0:
sources/cereal/archives/json.hpp:158:7: error: looser throw specifier for 'virtual cereal::JSONOutputArchive::~JSONOutputArchive()'
In file included from sources/cereal/archives/json.hpp:32:0,
from sources/main.cpp:25:
sources/cereal/cereal.hpp:234:9: error: overriding 'virtual cereal::OutputArchivecereal::JSONOutputArchive::~OutputArchive() noexcept (true)'
In file included from sources/main.cpp:25:0:
sources/cereal/archives/json.hpp:402:9: error: looser throw specifier for 'virtual cereal::JSONInputArchive::~JSONInputArchive()'
In file included from sources/cereal/archives/json.hpp:32:0,
from sources/main.cpp:25:
sources/cereal/cereal.hpp:584:9: error: overriding 'virtual cereal::InputArchivecereal::JSONInputArchive::~InputArchive() noexcept (true)'
In file included from sources/main.cpp:26:0:
sources/cereal/archives/xml.hpp:161:7: error: looser throw specifier for 'virtual cereal::XMLOutputArchive::~XMLOutputArchive()'
In file included from sources/cereal/archives/json.hpp:32:0,
from sources/main.cpp:25:
sources/cereal/cereal.hpp:234:9: error: overriding 'virtual cereal::OutputArchivecereal::XMLOutputArchive::~OutputArchive() noexcept (true)'
In file included from sources/main.cpp:26:0:
sources/cereal/archives/xml.hpp:374:9: error: looser throw specifier for 'virtual cereal::XMLInputArchive::~XMLInputArchive()'
In file included from sources/cereal/archives/json.hpp:32:0,
from sources/main.cpp:25:
sources/cereal/cereal.hpp:584:9: error: overriding 'virtual cereal::InputArchivecereal::XMLInputArchive::~InputArchive() noexcept (true)'

@erichkeane
changing json.hpp:158 with ~JSONOutputArchive() CEREAL_NOEXCEPT removes the two first errors (related to JSONOutputArchives).

adding ~JSONInputArchive() CEREAL_NOEXCEPT = default; in JSONInputArchive class provides a new error:

sources/cereal/archives/json.hpp:430:7: error: function 'virtual cereal::JSONInputArchive::~JSONInputArchive()' defaulted on its first declaration with an exception-specification that differs from the implicit declaration 'cereal::JSONInputArchive::~JSONInputArchive()'

If I remove = default; it's ok.

Applying the same strategy on XML archive, it compiles OK and provide the following output

<?xml version="1.0" encoding="utf-8"?>
<cereal>
    <windows>
        <height>101</height>
        <width>200</width>
        <enable>true</enable>
    </windows>
</cereal>

which seems to be ok.

To sumup:

json.hpp

@@ -155,7 +155,7 @@ namespace cereal
       }

       //! Destructor, flushes the JSON
-      ~JSONOutputArchive()
+      ~JSONOutputArchive() CEREAL_NOEXCEPT
       {
         if (itsNodeStack.top() == NodeType::InObject)
           itsWriter.EndObject();
@@ -427,6 +427,8 @@ namespace cereal
           itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
       }

+      ~JSONInputArchive() CEREAL_NOEXCEPT;
+
       //! Loads some binary data, encoded as a base64 string
       /*! This will automatically start and finish a node to load the data, and can be called directly by
           users.

xml.hpp

@@ -158,7 +158,7 @@ namespace cereal
       }

       //! Destructor, flushes the XML
-      ~XMLOutputArchive()
+      ~XMLOutputArchive() CEREAL_NOEXCEPT
       {
         const int flags = itsIndent ? 0x0 : rapidxml::print_no_indenting;
         rapidxml::print( itsStream, itsXML, flags );
@@ -412,6 +412,8 @@ namespace cereal
           itsNodes.emplace( root );
       }

+      ~XMLInputArchive() CEREAL_NOEXCEPT;
+
       //! Loads some binary data, encoded as a base64 string, optionally specified by some name
       /*! This will automatically start and finish a node to load the data, and can be called directly by
           users.

Can I safely use this patch for now ? and thanks for your help !

@erichkeane
Copy link
Contributor

The non-specified JSONInputArchie concerns me a little, since I fear you'll get a linker error when trying to use it. If you don't, then either something nasty is happening, or something I don't understand. I'd say at LEAST give it an empty body ( {}). Otherwise, it seems that this should be a fine patch.

Alternatively, if you have the ability, you could upgrade compilers to something more recent.

@DaemonPulsar
Copy link
Author

Of course you're right, linker is not really happy to deal with a non-specified destructor. Correct version is
~JSONInputArchive() CEREAL_NOEXCEPT {}
and
~XMLInputArchive() CEREAL_NOEXCEPT {}

I'll try to get a more recent compiler, also.

Thank again

@AzothAmmo
Copy link
Contributor

I'll commit the NOEXCEPT fix and push out a 1.2.1 release to fix this, which I think only affects GCC 4.7.3 and earlier.

@AzothAmmo
Copy link
Contributor

Should be fixed on develop, I'll push it out as a release either this weekend or on Monday along with the threading stuff from #320.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants