Updated static initializers

When MSVC init_seg or GCC init_priority is available, we don't need to use the Singleton. We only need to create a file scope class variable and place it in the segment for MSVC or provide the attribute for GCC.
An additional upside is we cleared all the memory leaks that used to be reported by MSVC for debug builds.
This commit is contained in:
Jeffrey Walton 2017-03-17 20:47:32 -04:00
parent bed31de2f6
commit 301437e693
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
7 changed files with 76 additions and 54 deletions

View File

@ -149,11 +149,13 @@
// __attribute__(init_priority(250)) is supported
#if (__GNUC__ && (CRYPTOPP_INIT_PRIORITY > 0) && ((CRYPTOPP_GCC_VERSION >= 40300) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (_INTEL_COMPILER >= 300)) && !(MACPORTS_GCC_COMPILER > 0) && !defined(__sun__))
# define HAVE_GCC_INIT_PRIORITY 1
# define HAVE_GCC_CONSTRUCTOR1 1
#endif
// __attribute__(init_priority()) is supported
#if (__GNUC__ && (CRYPTOPP_INIT_PRIORITY > 0) && !HAVE_GCC_CONSTRUCTOR1 && !(MACPORTS_GCC_COMPILER > 0) && !defined(__sun__))
# define HAVE_GCC_INIT_PRIORITY 1
# define HAVE_GCC_CONSTRUCTOR0 1
#endif

View File

@ -217,7 +217,7 @@ static inline bool IsVIA(const word32 output[4])
}
#if HAVE_GCC_CONSTRUCTOR1
void __attribute__ ((constructor (CRYPTOPP_INIT_PRIORITY + 50))) DetectX86Features()
void __attribute__ ((constructor (CRYPTOPP_INIT_PRIORITY + 20))) DetectX86Features()
#elif HAVE_GCC_CONSTRUCTOR0
void __attribute__ ((constructor)) DetectX86Features()
#else
@ -305,7 +305,7 @@ void DetectX86Features()
if (!g_cacheLineSize)
g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
*((volatile bool*)&g_x86DetectionDone) = true;
g_x86DetectionDone = true;
}
#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
@ -731,7 +731,7 @@ static bool TrySHA2()
}
#if HAVE_GCC_CONSTRUCTOR1
void __attribute__ ((constructor (CRYPTOPP_INIT_PRIORITY + 50))) DetectArmFeatures()
void __attribute__ ((constructor (CRYPTOPP_INIT_PRIORITY + 20))) DetectArmFeatures()
#elif HAVE_GCC_CONSTRUCTOR0
void __attribute__ ((constructor)) DetectArmFeatures()
#else

View File

@ -42,33 +42,30 @@ CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
#endif
#if HAVE_GCC_INIT_PRIORITY
CRYPTOPP_COMPILE_ASSERT(CRYPTOPP_INIT_PRIORITY >= 101);
const std::string DEFAULT_CHANNEL __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 25))) = "";
const std::string AAD_CHANNEL __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 26))) = "AAD";
#elif HAVE_MSC_INIT_PRIORITY
#pragma warning(disable: 4073)
#pragma init_seg(lib)
const std::string DEFAULT_CHANNEL = "";
const std::string AAD_CHANNEL = "AAD";
#pragma warning(default: 4073)
#else
static const std::string s1(""), s2("AAD");
const std::string DEFAULT_CHANNEL = s1;
const std::string AAD_CHANNEL = s2;
#endif
class NullNameValuePairs : public NameValuePairs
{
public:
NullNameValuePairs() {} // Clang complaint a default ctor must be avilable
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{CRYPTOPP_UNUSED(name); CRYPTOPP_UNUSED(valueType); CRYPTOPP_UNUSED(pValue); return false;}
};
#if HAVE_GCC_INIT_PRIORITY
const simple_ptr<NullNameValuePairs> s_pNullNameValuePairs __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 30))) = new NullNameValuePairs;
const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p;
const std::string DEFAULT_CHANNEL __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = "";
const std::string AAD_CHANNEL __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 11))) = "AAD";
const NullNameValuePairs s_nullNameValuePairs __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 12)));
const NameValuePairs &g_nullNameValuePairs = dynamic_cast<const NameValuePairs&>(s_nullNameValuePairs);
#elif HAVE_MSC_INIT_PRIORITY
#pragma warning(disable: 4073)
#pragma init_seg(lib)
const std::string DEFAULT_CHANNEL = "";
const std::string AAD_CHANNEL = "AAD";
const NullNameValuePairs s_nullNameValuePairs;
const NameValuePairs &g_nullNameValuePairs = dynamic_cast<const NameValuePairs&>(s_nullNameValuePairs);
#pragma warning(default: 4073)
#else
const std::string DEFAULT_CHANNEL = "";
const std::string AAD_CHANNEL = "AAD";
const simple_ptr<NullNameValuePairs> s_pNullNameValuePairs(new NullNameValuePairs);
const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p;
#endif

View File

@ -49,10 +49,10 @@
// "Error: The operand ___LKDB cannot be assigned to", http://github.com/weidai11/cryptopp/issues/188
#if (__SUNPRO_CC >= 0x5130)
# define MAYBE_CONST
# define MAYBE_UNCONST_CAST const_cast<word*>
# define MAYBE_UNCONST_CAST(x) const_cast<word*>(x)
#else
# define MAYBE_CONST const
# define MAYBE_UNCONST_CAST
# define MAYBE_UNCONST_CAST(x) x
#endif
// "Inline assembly operands don't work with .intel_syntax",
@ -69,6 +69,51 @@
# define CRYPTOPP_INTEGER_SSE2 (CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86))
#endif
NAMESPACE_BEGIN(CryptoPP)
template <long i>
struct NewInteger
{
Integer * operator()() const
{
return new Integer(i);
}
};
static void SetFunctionPointers();
bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt);
NAMESPACE_END
ANONYMOUS_NAMESPACE_BEGIN
struct InitializeInteger
{
InitializeInteger()
{
CryptoPP::SetFunctionPointers();
CryptoPP::g_pAssignIntToInteger = (CryptoPP::PAssignIntToInteger)CryptoPP::AssignIntToInteger;
}
};
#if HAVE_GCC_INIT_PRIORITY
const InitializeInteger s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 30))) = InitializeInteger();
const CryptoPP::Integer s_zero __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 31))) = CryptoPP::Integer(0L);
const CryptoPP::Integer s_one __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 32))) = CryptoPP::Integer(1L);
const CryptoPP::Integer s_two __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 33))) = CryptoPP::Integer(2L);
#elif HAVE_MSC_INIT_PRIORITY
#pragma warning(disable: 4073)
#pragma init_seg(lib)
const InitializeInteger s_init;
const CryptoPP::Integer s_zero(0L);
const CryptoPP::Integer s_one(1L);
const CryptoPP::Integer s_two(2L);
#pragma warning(default: 4073)
#else
const InitializeInteger& s_init = CryptoPP::Singleton<InitializeInteger>().Ref();
const CryptoPP::Integer& s_zero = CryptoPP::Singleton<CryptoPP::Integer, CryptoPP::NewInteger<0L> >().Ref();
const CryptoPP::Integer& s_one = CryptoPP::Singleton<CryptoPP::Integer, CryptoPP::NewInteger<1L> >().Ref();
const CryptoPP::Integer& s_two = CryptoPP::Singleton<CryptoPP::Integer, CryptoPP::NewInteger<2L> >().Ref();
#endif
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt)
@ -2069,7 +2114,13 @@ static PMul s_pMul[9], s_pBot[9];
static PSqu s_pSqu[9];
static PMulTop s_pTop[9];
static void SetFunctionPointers()
#if HAVE_GCC_CONSTRUCTOR1
void __attribute__ ((constructor (CRYPTOPP_INIT_PRIORITY + 35))) SetFunctionPointers()
#elif HAVE_GCC_CONSTRUCTOR0
void __attribute__ ((constructor)) SetFunctionPointers()
#else
void SetFunctionPointers()
#endif
{
s_pMul[0] = &Baseline_Multiply2;
s_pBot[0] = &Baseline_MultiplyBottom2;
@ -2854,15 +2905,6 @@ void MultiplyByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t
// ******************************************************************
InitializeInteger::InitializeInteger()
{
if (!g_pAssignIntToInteger)
{
SetFunctionPointers();
g_pAssignIntToInteger = (CryptoPP::PAssignIntToInteger)AssignIntToInteger;
}
}
static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8};
static inline size_t RoundupSize(size_t n)
@ -3003,34 +3045,16 @@ Integer Integer::Power2(size_t e)
return r;
}
template <long i>
struct NewInteger
{
Integer * operator()() const
{
return new Integer(i);
}
};
// File scope static due to subtle initialization problems in a threaded
// Windows environment. See the comments for Singleton. Thanks DB.
namespace { const Integer& s_zero = Singleton<Integer>().Ref(); }
const Integer &Integer::Zero()
{
return s_zero;
}
// File scope static due to subtle initialization problems in a threaded
// Windows environment. See the comments for Singleton. Thanks DB.
namespace { const Integer& s_one = Singleton<Integer, NewInteger<1> >().Ref(); }
const Integer &Integer::One()
{
return s_one;
}
// File scope static due to subtle initialization problems in a threaded
// Windows environment. See the comments for Singleton. Thanks DB.
namespace { const Integer& s_two = Singleton<Integer, NewInteger<2> >().Ref(); }
const Integer &Integer::Two()
{
return s_two;

View File

@ -40,7 +40,7 @@ typedef SecBlock<word, AllocatorWithCleanup<word, true> > IntegerSecBlock;
//! used to track the sign of the Integer.
//! \since Crypto++ 1.0
//! \nosubgrouping
class CRYPTOPP_DLL Integer : private InitializeInteger, public ASN1Object
class CRYPTOPP_DLL Integer : public ASN1Object
{
public:
//! \name ENUMS, EXCEPTIONS, and TYPEDEFS

View File

@ -27,7 +27,7 @@
// For Linux, NASM is optional. Run rdrand-nasm.sh, and then make
// with "USE_NASM" like so: USE_NASM=1 make -j 4. The makefile
// will add the appropriate defines when building rdrand.cpp,
// will add the appropriate defines when building rdrand.cpp,
// and add the appropriate object file during link.
#if 0

View File

@ -71,7 +71,6 @@ being unloaded from L1 cache, until that round is finished.
#ifndef CRYPTOPP_GENERATE_X64_MASM
#include "rijndael.h"
#include "stdcpp.h" // alloca
#include "misc.h"
#include "cpu.h"