Click here to Skip to main content
15,887,485 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm working on a framework that is used within managed code, but relies on the native 3rd party library cereal[^]. I might have a problem with cereal's use of static variables: their instantiation causes Visual Studio to issue the warning C4835[^]. It's a level 1 warning, so I''m not taking it lightly, and although the program compiles and runs, I have a suspicion there is something not quite right.

I've found this suggestion[^] which should tell the compiler to compile this code as native, but although cereal is header only, this tip doesn't work for the code that actually invokes cereal using the macro
CEREAL_CLASS_VERSION(,)
.

I've only started working with managed code, and duckduckgo-ing for a solution got me this far (see links above). googl-ing didn't get me any further. Does anyone here have an idea how to properly resolve this without modifying the cereal headers, and without disabling the warning? Otherwise, can anyone familiar with ceral tell me whether or not the warning can be safely ignored? As far as I can tell I shouldn't, but I may be wrong.

What I have tried:

C++
#pragma managed(push, off)
#include "cereal.hpp" // normally produces C4835, but not with the help of this pragma
class foo { int x; };
CEREAL_CLASS_VERSION(foo, 0); // warning C4835 issued in spite of pragma!
#pragma managed(pop)


I've managed to pinpoint the locations (2 positions) within Cereal that are causing the issue. By adding the abovementioned #pragma statements in these locations, I could reliably eliminate the warning. See below:
C++
namespace cereal
{
  namespace detail
  {
    //! A static, pre-execution object
    /*! This class will create a single copy (singleton) of some
        type and ensures that merely referencing this type will
        cause it to be instantiated and initialized pre-execution.
        For example, this is used heavily in the polymorphic pointer
        serialization mechanisms to bind various archive types with
        different polymorphic classes */
    template <class T>
    class CEREAL_DLL_EXPORT StaticObject
    {
      private:

        static T & create()
        {
#pragma warning(push)
#pragma warning(disable : 4835)
			static T t;
#pragma warning(pop)
			//! Forces instantiation at pre-execution time
          (void)instance;
          return t;
        }

        StaticObject( StaticObject const & /*other*/ ) {}

      public:
        static T & getInstance()
        {
          return create();
        }

        //! A class that acts like std::lock_guard
        class LockGuard
        {
          #if CEREAL_THREAD_SAFE
          public:
            LockGuard(std::mutex & m) : lock(m) {}
          private:
            std::unique_lock<std::mutex> lock;
          #else
          public:
	          LockGuard(LockGuard const &) = default; // prevents implicit copy ctor warning
            ~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used
          #endif
        };

        //! Attempts to lock this static object for the current scope
        /*! @note This function is a no-op if cereal is not compiled with
                  thread safety enabled (CEREAL_THREAD_SAFE = 1).

            This function returns an object that holds a lock for
            this StaticObject that will release its lock upon destruction. This
            call will block until the lock is available. */
        static LockGuard lock()
        {
          #if CEREAL_THREAD_SAFE
          static std::mutex instanceMutex;
          return LockGuard{instanceMutex};
          #else
          return LockGuard{};
          #endif
        }

      private:
        static T & instance;
    };

#pragma warning(push)
#pragma warning(disable : 4835)
    template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
#pragma warning (pop)
  } // namespace detail
} // namespace cereal


The question remains whether it's actually safe to ignore this warning, or if there is a reasonable way to properly fix it other than modifying 3rd party code!
Posted
Updated 17-Dec-20 6:04am
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900