Reading a lot about this well known problem I discovered and used the "Creation on first use", but it main problem is that it produces memory leaks.
Working a bit, I've done some light modification trying to solve that problem, and I got a solution:
1) Using a global static pointer instead a local static pointer
2) Using a separate function to delete the object.
Example:
static myObject* myObjectPtr=nullptr;
static myObjectDel() {delete myObjectPtr;}
inline myObject& myObjectRef()
{
if(myObjectPtr==nullptr)
{
myObjectPtr=new myObjectPtr;
atexit(myObjectDel);
}
return(*myObjectPtr);
}
So, I can ensure that:
1) The object is created before first use.
2) The object is deleted after last use.
3) There are no memory leaks.
It works with MS Visual Studio 2013 due the static pointer is zero-initialized at program startup, but I'm not sure if all compilers and operating systems does it.
In other words, Is it portable?
Thanks you and sorry for my poor english (I'm not english native)
Your solution is portable, but it's not thread-safe.
It's also needlessly complicated.
Don't use dynamic allocation:
inline myObject& myObjectRef()
{
static myObject theObject;
return theObject;
}
Leak-free (since the dawn of time) and thread-safe (since C++11).
I'd prefer static myObject* myObjectPtr; since all static pointers will be initialised to nullptr anyway. The C++ standard guarantees that.
But your code is vulnerable to two threads calling inline myObject& myObjectRef() for the first time which could lead to multiple new to be balanced with only one delete. You ought to use a mutex in that function to obviate that.
Related
I have a function call
void moveMeToThread(UnsafeStruct *ptr)
{
// do stuff with ptr
}
Now I want to move moveMeToThread to a different thread, so I do not want anyone creating an object of UnsafeStruct on the stack and I also want memory of all UnsafeStruct objects made on the heap to be freed automatically. Anyone have an elegant way to do this?
Sounds like you'd like to make a heap-only class. There are many ways to force this:
you might make private ctors (all of them!) and create a static create() function that returns a pointer (sometimes called named ctor)
you might make dtor private
The latter technically does not save you from placement new to a suitable memory block, but otherwise protects from sensible coding mistakes and is way more compatible with algorithms and containers. E.g. you can still copy such an object via copy ctor outside the class, which is not possible if you make all ctors private (which is a requirement for the first version).
You might do this:
template<typename T>
class HeapOnly
{
public:
T t;
operator T&() { return t; }
operator const T&() const { return t; }
private:
~HeapOnly();
};
void moveMeToThread(HeapOnly<UnsafeStruct> *ptr)
{ /* ... */ }
int main()
{
HeapOnly<UnsafeStruct> *ptr =
new HeapOnly<UnsafeStruct>{/* args to UnsafeStruct */};
moveToThread(ptr);
}
Small note: there's no such thing as (call/parameter) stack in the C++ standard. It only appears in ItaniumABI (and potentially in other ABIs). Standard says ASDV (automatic storage duration variables) for what's commonly referred to as 'on the stack', but nothing prevents an implementation to allocate the memory on the stack (as long as compiler can prove that the object's lifetime cannot extend the stack unroll - this works e.g. if it's allocated before static initialization). It might be completely unimportant in your case, but in security-related codes, where buffer overflow is important, you can't strictly enforce not having objects allocated from the same stack this way (and thus it's suggested to do a runtime check) - but you can still enforce that the object is allocated via new (or the given static member function).
I do not want anyone creating an object of UnsafeStruct on the stack.
I want to forbid it because if someone creates an object on the stack and sends it on the thread, it can cause a crash(dangling pointer)
Do you also want to prevent anybody from creating int variables on the stack? Because if somebody creates an int variable on the stack, and if they allow a reference or a pointer to it to outlive the stack frame that contains the variable, then their program could crash.
Seriously.
That problem is older than C++. That problem has existed since the very first edition of the C programming language. Every C and C++ programmer has to learn not to do that. Always have. Always will.
In some languages (e.g., Java, Python), No object of any kind can be allocated anywhere else except the garbage-collected heap. Variables can only hold references to objects, and dangling references are impossible. Programmers in those languages expect an assignment a=b to copy an object reference. That is, after the assignment, a and b both refer to the same object.
That's not the C++ way. C++ programmers expect that if some type T is publicly constructable, then they expect to be allowed to declare one wherever they want. And when they see a=b, they think of that assignment operator as copying a value. They expect that after the assignment, a and b still are two different objects that both have (in some sense) the same "value."
You will find more people saying positive things about your library if you design it to work in that same way.
I have inherited a pile of C++ code, saturated with std::shared_ptrs, most [all?] of which are unnecessary and are, I suspect, degrading performance. It is not feasible to change everything in one go, so I'm changing the code in tranches and doing performance tests.
An issue I'm running into is the interface in the method hierarchy between my new "raw" pointer code, and the underlying shared_ptr stuff. A contrived example (I know it could be simplified...):
SomeObject *MyClass::GetSomeObject(const std::string& aString)
{
//for the underlying shared pointer methods
std::shared_ptr<std::string> tmpString = make_shared<std::string>(aString);
//call the method using my local shared pointer
std::shared_ptr<SomeObject> someObj = GetTheObject(tmpString);
//The line below gives compiler warning: "The pointer points to memory allocated on the stack"
return someObj.get(); // a pointer to an object in std::map
}
I know that GetTheObject() is returning a pointer to an object in a persistent std::map, so that memory will be in good standing after we exit GetSomeObject() and the shared pointer [and its wrapped raw pointer] have gone out of scope.
I'm not in the habit of ignoring warnings, SO:
Questions:
Is the warning because the compiler is worried about the scope of the shared pointer rather than the object pointed to? [i.e. could I ignore it in this instance?]
If it is a real problem, are there any neat ways around this (that do not involve building wrapper classes and such workarounds...) ?
If I understand you correctly, you're replacing smart pointers with dumb pointers, in 2021, and you're now facing the exact problem that smart pointers intended to solve.
The warning is 100% accurate, and I'm pleasantly surprised the compiler looked deep enough.
The solution is simple: return a shared_ptr<SomeObject>. If you want efficiency improvements, there are two real improvements possible. C++11 introduced move constructors, and moving shared_ptr is faster than copying. The compiler will use the move ctor for return someObj; since someObj goes out of scope
Secondly, shared_ptr is a heavy-weight alternative to unique_ptr. At times, you may be able to downgrade to the latter.
I have similar code in my project. I agree that the proper solution is probably just to commit fully to the smart pointers and use them properly. However, I don't want to churn through piles of perfectly functional code, but I also want the warnings to go away. I was able to work around the warning with something like:
SomeObject *MyClass::GetSomeObject(const std::string& aString)
{
//for the underlying shared pointer methods
std::shared_ptr<std::string> tmpString = make_shared<std::string>(aString);
//call the method using my local shared pointer
std::shared_ptr<SomeObject> someObj = GetTheObject(tmpString);
SomeObject *pRet = someObj.get();
return pRet; // a pointer to an object in std::map
}
I'm a little worried that at some point the compiler will get smarter and detect that as a warning as well, but it seems OK for now. (Visual Studio 2022 v17.1) Hope that helps!
I recently came across the Nifty Counter Idiom. My understanding is that this is used to implement globals in the standard library like cout, cerr, etc. Since the experts have chosen it, I assume that it's a very strong technique.
I'm trying to understand what the advantage is over using something more like a Meyer Singleton.
For example, one could just have, in a header file:
inline Stream& getStream() { static Stream s; return s; }
static Stream& stream = getStream();
The advantage is you don't have to worry about reference counting, or placement new, or having two classes, i.e. the code is much simpler. Since it's not done this way, I'm sure there's a reason:
Is this not guaranteed to have a single global object across shared and static libraries? It seems like the ODR should guarantee that there can only be one static variable.
Is there some kind of performance cost? It seems like in both my code and the Nifty Counter, you are following one reference to get to the object.
Is there some situations where the reference counting is actually useful? It seems like it will still just lead to the object being constructed if the header is included, and destroyed at program end, like the Meyer Singleton.
Does the answer involve dlopen'ing something manually? I don't have too much experience with that.
Edit: I was prompted to write the following bit of code while reading Yakk's answer, I add it to the original question as a quick demo. It's a very minimal example that shows how using the Meyer Singleton + a global reference leads to initialization before main: http://coliru.stacked-crooked.com/a/a7f0c8f33ba42b7f.
The static local/Meyer's singleton + static global reference (your solution) is nearly equivalent to the nifty counter.
The differences are as follows:
No .cpp file is required in your solution.
Technically the static Steam& exists in every compilation unit; the object being referred to does not. As there is no way to detect this in the current version of C++, under as-if this goes away. But some implementations might actually create that reference instead of eliding it.
Someone could call getStream() prior to the static Stream& being created; this would cause difficulty in destruction order (with the stream being destroyed later than expected). This can be avoided by making that against the rules.
The standard is mandated to make creating the static Stream local in the inline getStream thread safe. Detecting that this is not going to happen is challenging for the compiler, so some redundant thread-safety overhead may exist in your solution. The nifty counter does not support thread safety explicitly; this is considered safe as it runs at static initialization time, prior to when threads are expected.
The call to getStream() must occur in each and every compilation unit. Only if it is proven that it cannot do anything may it be optimized out, which is difficult. The nifty counter has a similar cost, but the operation may or may not be be simpler to optimize out or in runtime cost. (Determining this will require inspecting resulting assembly output on a variety of compilers)
"magic statics" (statics locals without race conditions) where introduced in C++11. There could be other issues prior to C++11 magic statics with your code; the only one I can think of is someone calling getStream() directly in another thread during static initialization, which (as mentioned above) should be banned in general.
Outside the realm of the standard, your version will automatically and magically create a new singleton in each dynamicly linked chunk of code (DLL, .so, etc). The nifty counter will only create the singleton in the cpp file. This may give the library writer tighter control over accidentally spawning new singletons; they can stick it into the dynamic library, instead of spawning duplicates.
Avoiding having more than one singleton is sometimes important.
Summarizing the answers and comments:
Let's compare 3 different options for a library, wishing to present a global Singleton, as a variable or via a getter function:
Option 1 - the nifty counter pattern, allowing the use of a global variable that is:
assured to be created once
assured to be created before the first usage
assured to be created once across all shared objects that are dynamically linked with the library creating this global variable.
Option 2 - the Meyers singleton pattern with a reference variable (as presented in the question):
assured to be created once
assured to be created before the first usage
However, it will create a copy of the singleton object in shared objects, even if all shared objects and the main are linked dynamically with the library. This is because the Singleton reference variable is declared static in a header file and must have its initialization ready at compile time wherever it is used, including in shared objects, during compile time, before meeting the program they will be loaded to.
Option 3 - the Meyers singleton pattern without a reference variable (calling a getter for retrieving the Singleton object):
assured to be created once
assured to be created before the first usage
assured to be created once across all shared objects that are dynamically linked with the library creating this Singleton.
However, in this option there is no global variable nor inline call, each call for retrieving the Singleton is a function call (that can be cached on the caller side).
This option would look like:
// libA .h
struct A {
A();
};
A& getA();
// some other header
A global_a2 = getA();
// main
int main() {
std::cerr << "main\n";
}
// libA .cpp - need to be dynamically linked! (same as libstdc++ is...)
// thus the below shall be created only once in the process
A& getA() {
static A a;
return a;
}
A::A() { std::cerr << "construct A\n"; }
All of your questions about utility / performance of Nifty Counter aka Schwartz Counter were basically answered by Maxim Egorushkin in this answer (but see also the comment threads).
Global variables in modern C++
The main issue is that there is a trade-off taking place. When you use Nifty Counter your program startup time is a bit slower (in large projects), since all these counters have to run before anything can happen. That doesn't happen in Meyer's singleton.
However, in the Meyer's singleton, every time you want to access the global object, you have to check if it's null, or, the compiler emits code that checks if the static variable was already constructed before any access is attempted. In the Nifty Counter, you have your pointer already and you just fire away, since you can assume the init happened at startup time.
So, Nifty Counter vs. Meyer's singleton is basically a trade-off between program startup time and run-time.
With the solution you have here, the global stream variable gets assigned at some point during static initialization, but it is unspecified when. Therefore the use of stream from other compilation units during static initialization may not work. Nifty counter is a way to guarantee that a global (e.g. std::cout) is usable even during static initialization.
#include <iostream>
struct use_std_out_in_ctor
{
use_std_out_in_ctor()
{
// std::cout guaranteed to be initialized even if this
// ctor runs during static initialization
std::cout << "Hello world" << std::endl;
}
};
use_std_out_in_ctor global; // causes ctor to run during static initialization
int main()
{
std::cout << "Did it print Hello world?" << std::endl;
}
Disclaimer: I come from a Java background, and, as such, I have no clue on how a lot of the internals of C++ (and associated libraries) work.
I have read enough to know that double-checked locking is evil, and a correct and safe implementation of a singleton pattern requires the appropriate tools.
I believe the following code may be unsafe, subject to compiler reordering and assignment of uninitialized objects, but I am not sure if I am missing something that I do not understand about the language.
typedef boost::shared_ptr<A> APtr;
APtr g_a;
boost::mutex g_a_mutex;
const APtr& A::instance()
{
if (!g_a)
{
boost::mutex::scoped_lock lock(g_a_mutex);
if (!g_a)
{
g_a = boost::make_shared<A>();
}
}
return g_a;
}
I believe the actual code is compiled under C++03.
Is this implementation unsafe? If so, how?
Yes, the double-checked locking pattern is unsafe in archaic languages. I can't do any better than the explanation in What's wrong with this fix for double checked locking?:
The problem apparently is the line assigning instance -- the compiler is free to allocate the object and then assign the pointer to it, OR to set the pointer to where it will be allocated, then allocate it.
If you were using C++11 std::shared_ptr, you could use atomic_load and atomic_store on the shared pointer object, which are guaranteed to compose correctly with each other and with mutexes; but if you're using C++11 you may as well just use a dynamically-initialized static variable, which is guaranteed to be thread-safe.
All of this is absolutelty unneccesary in modern C++. Singleton code should be as simple as this for anybody but dinosaurs:
A& A::instance() {
static A a;
return a;
}
100% thread safe in C++11 and up.
However, I have a mandatory statement to make: Singletons are evil antipattern and should be banned forever.
On thread safety of original code
Yes, provided code is unsafe. Since the reading is done outside the mutex, it is totally possible that the modifications to g_a itself would be visible, but not that modifications to the object g_a is pointing to. As a result, the thread will bypass mutex locking and return a pointer to non-constructed object.
My specific question is that when implementing a singleton class in C++, is there any substantial differences between the two below codes regarding performance, side issues or something:
class singleton
{
// ...
static singleton& getInstance()
{
// allocating on heap
static singleton* pInstance = new singleton();
return *pInstance;
}
// ...
};
and this:
class singleton
{
// ...
static singleton& getInstance()
{
// using static variable
static singleton instance;
return instance;
}
// ...
};
(Note that dereferencing in the heap-based implementation should not affect performance, as AFAIK there is no extra machine-code generated for dereferencing. It's seems only a matter of syntax to distinguish from pointers.)
UPDATE:
I've got interesting answers and comments which I try to summarize them here. (Reading detailed answers is recommended for those interested.):
In the singleton using static local variable, the class destructor is automatically invoked at process termination, whereas in the dynamic allocation case, you have to manage object destruction someway at sometime, e.g. by using smart pointers:
static singleton& getInstance() {
static std::auto_ptr<singleton> instance (new singleton());
return *instance.get();
}
The singleton using dynamic allocation is "lazier" than the static singleton variable, as in the later case, the required memory for the singleton object is (always?) reserved at process start-up (as part of the whole memory required for loading program) and only calling of the singleton constructor is deferred to getInstance() call-time. This may matter when sizeof(singleton) is large.
Both are thread-safe in C++11. But with earlier versions of C++, it's implementation-specific.
The dynamic allocation case uses one level of indirection to access the singleton object, whereas in the static singleton object case, direct address of the object is determined and hard-coded at compile-time.
P.S.: I have corrected the terminology I'd used in the original posting according to the #TonyD's answer.
the new version obviously needs to allocate memory at run-time, whereas the non-pointer version has the memory allocated at compile time (but both need to do the same construction)
the new version won't invoke the object's destructor at program termination, but the non-new version will: you could use a smart pointer to correct this
you need to be careful that some static/namespace-scope object's destructors don't invoke your singleton after its static local instance's destructor has run... if you're concerned about this, you should perhaps read a bit more about Singleton lifetimes and approaches to managing them. Andrei Alexandrescu's Modern C++ Design has a very readable treatment.
under C++03, it's implementation-defined whether either will be thread safe. (I believe GCC tends to be, whilst Visual Studio tends not -comments to confirm/correct appreciated.)
under C++11, it's safe: 6.7.4 "If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization." (sans recursion).
Discussion re compile-time versus run-time allocation & initialisation
From the way you've worded your summary and a few comments, I suspect you're not completely understanding a subtle aspect of the allocation and initialisation of static variables....
Say your program has 3 local static 32-bit ints - a, b and c - in different functions: the compiler's likely to compile a binary that tells the OS loader to leave 3x32-bits = 12 bytes of memory for those statics. The compiler decides what offsets each of those variables is at: it may put a at offset 1000 hex in the data segment, b at 1004, and c at 1008. When the program executes, the OS loader doesn't need to allocate memory for each separately - all it knows about is the total of 12 bytes, which it may or may not have been asked specifically to 0-initialise, but it may want to do anyway to ensure the process can't see left over memory content from other users' programs. The machine code instructions in the program will typically hard-code the offsets 1000, 1004, 1008 for accesses to a, b and c - so no allocation of those addresses is needed at run-time.
Dynamic memory allocation is different in that the pointers (say p_a, p_b, p_c) will be given addresses at compile time as just described, but additionally:
the pointed-to memory (each of a, b and c) has to be found at run-time (typically when the static function first executes but the compiler's allowed to do it earlier as per my comment on the other answer), and
if there's too little memory currently given to the process by the Operating System for the dynamic allocation to succeed, then the program library will ask the OS for more memory (e.g. using sbreak()) - which the OS will typically wipe out for security reasons
the dynamic addresses allocated for each of a, b and c have to be copied back into the pointers p_a, p_b and p_c.
This dynamic approach is clearly more convoluted.
The main difference is that using a local static the object will be destroyed when closing the program, instead heap-allocated objects will just be abandoned without being destroyed.
Note that in C++ if you declare a static variable inside a function it will be initialized the first time you enter the scope, not at program start (like it happens instead for global static duration variables).
In general over the years I switched from using lazy initialization to explicit controlled initialization because program startup and shutdown are delicate phases and quite difficult to debug. If your class is not doing anything complex and just cannot fail (e.g. it's just a registry) then even lazy initialization is fine... otherwise being in control will save you quite a lot of problems.
A program that crashes before entering the first instruction of main or after executing last instruction of main is harder to debug.
Another problem of using lazy construction of singletons is that if your code is multithread you've to pay attention to the risk of having concurrent threads initializing the singleton at the same time. Doing initialization and shutdown in a single thread context is simpler.
The possible races during initialization of function-level static instances in multithreaded code has been resolved since C++11, when the language added official multithreading support: for normal cases proper synchronization guards are automatically added by the compiler so this is not a concern in C++11 or later code. However if initialization of a static in function a calls function b and vice-versa you can risk a deadlock if the two functions are called the first time at the same time by different threads (this is not an issue only if the compiler uses a single mutex for all statics). Note also that calling the function that contains a static object from within the initialization code of the static object recursively is not permitted.