This is a simplification of an issue I encountered in another project.
Say I have the following class:
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructed\n";
Instances().insert(this);
}
~MyClass() {
std::cout << "MyClass destructed\n";
Instances().erase(this);
}
static std::unordered_set<MyClass*>& Instances() {
static std::unordered_set<MyClass*> _instances;
return _instances;
}
};
It has a static unordered_set that it uses for keeping track of existing instances of the class. When an instance is constructed, its address is added to the set; when an instance is destroyed, its address is removed from the set.
Now, I have another class that has a vector of shared_ptrs containing instances of MyClass:
struct InstanceContainer {
std::vector<std::shared_ptr<MyClass>> instances;
};
A key point here is that there is a global instance of this class above main. This seems to be part of the problem, because declaring the class inside of main does not produce the issue.
Inside of main, I do the following (say the global instance of InstanceContainer is called container):
container.instances.emplace_back(std::shared_ptr<MyClass>(new MyClass));
Everything is fine until the program terminates, when I get a read access violation ("vector subscript out of range") when Instances().erase(this) is executed in MyClass's destructor.
I thought that maybe I was attempting to erase the instance from _instances multiple times (hence the couts)-- However, the contructor is only called once, and the destructor is only called once, as you'd expect. I found that when this happens, _instances.size() is equal to 0. The weird thing is, it's equal to 0 before any calls to erase. Prior to anything being erased from the set, it's empty?!
My theory at this point is that this has to do with the order in which the objects are destructed as the program terminates. Perhaps the static _instances is being freed before the destructor for MyClass is called.
I was hoping someone would be able to shed some light on this, and confirm whether or not that's what's happening.
My workaround now is to check to see if _instances.size() is 0 before attempting to erase. Is this safe? If not, what else can I do?
If it matters, I'm using MSVC. Here's an executable example.
Here's what happens. That global variable of type InstanceContainer is constructed first, before main is entered. The function-static variable _instances is created later, when Instances() is called for the first time.
At program shutdown, destructors for these objects are called in the reverse order of construction. Therefore, _instances is destroyed first, and then InstanceContainer, which in turn destroys its vector of shared pointers, which in turn run ~MyClass on all objects still in the vector, which in turn call _instances.erase() on already-destroyed _instances. Whereupon your program exhibits undefined behavior by way of accessing an object whose lifetime has ended.
There are several ways you could work around this. One, you could ensure that InstanceContainer::instances is empty before main returns. No idea how feasible this is, as you've never explained what role InstanceContainer plays in your design.
Two, you could allocate _instances on the heap, and just leak it:
static std::unordered_set<MyClass*>& Instances() {
static auto* _instances = new std::unordered_set<MyClass*>;
return *_instances;
}
This will keep it alive through the destruction of global objects.
Three, you could put something like this before the definition of InstanceContainer global variable:
static int dummy = (MyClass::Instances(), 0);
This will ensure that _instances is created earlier, and therefore destroyed later.
Related
Good Day,
I usually find it best to look at other people's code when I try to learn a programming language.
I am now trying to learn C++ but having some trouble understanding the following function (as an example):
Vehicle* MyClass::GetVehicleByID(uint id)
{
Vehicle* car = new Vehicle;
car->model = vehiclesArray[id].model;
return car;
}
int main()
{
Vehicle* car = myClass.GetVehicleID(0);
std::cout << "Car Model: " << car->model << std::endl;
}
I think I understand the concept of pointers. But I don't understand when this object will be destroyed. Will I have to manually delete the object "car" in the main function? Also, why are we using the new keyword instead of just using "Vehicle car();"? As I understand it the new keyword will allocate memory before populating it with the object?
Am I completely out of my depth just by asking these questions? Where or how can I learn to understand what is going on in this code? Because it seems like all tutorials only explain the "basics" like what a pointer is and the most basic way of using them.
Any help would be much appreciated.
Yes, if you create an object with new keyword, you will have to delete it with delete keyword. There is no garbage collection in C++. So in your case, this would be:
delete car;
Also, the difference between creating with new and just using the constructor directly as you suggest is that with new, the object is created on the heap, and it's lifetime is extended until it is explicitly deleted by the programmer. In the other case, it will be created on the stack and will be deleted automatically as soon as the enclosing funcion or block is exited.
What happens in your case is that you create an object on the heap and never delete it. This causes a so-called memory leak. Since your program is small, this is not an issue and this memory is released after the program finishes. However, in a case of a long running program, or a program that often allocates on the heap, it can cause the program to run out of available memory.
Also note that you could create an object inside the function, change the signature to return an object instead of a pointer, and have the function return that object directly. This would work, but what would happen is that first an object local to the function would be created on the stack. Then that object would be copied into another object created in the main function, and the first object would then be deleted. This is not very efficient, that is why a pointer to an objecet allocated on the heap is used. One reason more to use the heap would be for storing large objects. The stack is small compared to the heap, and should not be used to store very large objects.
I hope this clarifies it a bit, but to understand all this well takes a lot of time and work, on stackoverflow answer is not enough. Iwould suggest to read more about differences between objects on heap and object on stack in C++. There is an abundance of information online.
Just for your question of code.
Maybe it's better to use shared_ptr instead of pointer
#include <memory>
std::shared_ptr<Vehicle> MyClass::GetVehicleByID(uint id)
{
std::shared_ptr<Vehicle> car = std::make_shared<Vehicle>();
car->model = vehiclesArray[id].model;
return car;
}
int main()
{
std::shared_ptr<Vehicle> car = myClass.GetVehicleID(0);
std::cout << "Car Model: " << car->model << std::endl;
}
the class shared_ptr is based on RAII guidelines. So you may not have to delete it. When main() end, the destructor shared_ptr::~shared_ptr() will be called and the pointer will be delete.
Anyway, it's a good idea to read <C++ Primer>
I just read, that this construct:
const bg::AppSettings& bg::AppSettings::GetInstance()
{
static AppSettings instance;
return instance;
}
is a thread safe and working way to create a singleton?! Am I correct, that the static AppSettings variable will be the same, every time I call this method?! I get a little bit confused about the scoping on this one ...
My normal approach was to use a unique_ptr as a static member of my class ... but this seems to work...can someone explain to me, what's going on here?!
And btw.: does the const make sense here?!
In C++11 (and forward), the construction of the function local static AppSettings is guaranteed to be thread-safe. Note: Visual Studio did not implement this aspect of C++11 until VS-2015.
The compiler will lay down a hidden flag along side of AppSettings that indicates whether it is:
Not constructed.
Being constructed.
Is constructed.
The first thread through will find the flag set to "not constructed" and attempt to construct the object. Upon successful construction the flag will be set to "is constructed". If another thread comes along and finds the flag set to "being constructed", it will wait until the flag is set to "is constructed".
If the construction fails with an exception, the flag will be set to "not constructed", and construction will be retried on the next pass through (either on the same thread or a different thread).
The object instance will remain constructed for the remainder of your program, until main() returns, at which time instance will be destructed.
Every time any thread of execution passes through AppSettings::GetInstance(), it will reference the exact same object.
In C++98/03, the construction was not guaranteed to be thread safe.
If the constructor of AppSettings recursively enters AppSettings::GetInstance(), the behavior is undefined.
If the compiler can see how to construct instance "at compile time", it is allowed to.
If AppSettings has a constexpr constructor (the one used to construct instance), and the instance is qualified with constexpr, the compiler is required to construct instance at compile time. If instance is constructed at compile time, the "not-constructed/constructed" flag will be optimized away.
The behavior of your code is similar to this:
namespace {
std::atomic_flag initialized = ATOMIC_FLAG_INIT;
std::experimental::optional<bg::AppSettings> optional_instance;
}
const bg::AppSettings& bg::AppSettings::GetInstance()
{
if (!initialized.test_and_set()) {
optional_instance.emplace();
}
return *optional_instance;
}
By having a thread-safe flag that lives for the entire duration of the program, the compiler can check this flag each time the function is called and only initialize your variable once. A real implementation can use other mechanisms to get this same effect though.
In a constructor for a class Block i push the created instance into a static vector static std::vector<Block*> allBlocks, and remove them in the destructor.
This works if i just create blocks without pointers, ie. Block b;
However, want to have another class return a std::vector<Block*> grid for use, which creates them and adds them into the allBlocks vector also. Destroying the grid vector doesn't seem to run their destructors.
I've tried:
grid.clear() using erase/remove and just pop_back
What would be a better way to store/return them so that when the grid is destroyed, so will the contained Blocks.
Okay, so if you want a really better way, a couple of changes:
No statics! They aren't necessary at all here.
If, as you've stated, you want two containers containing those objects but in such a way that removing one object removes them from every other container, it becomes more problematic.
First, it's impossible for one container to remove elements from another unless it has a reference to it in a way. You could create a variable that would hold all of the containers of your blocks and use that to remove the block from every container, but... yeah.
In this case, a weak reference solution is acceptable, as long as you remember about the implications.
std::shared_ptr ownership and std::weak_ptr reference
Create an std::set<shared_ptr<Block>> blocks;, then two containers with weak references; might be called allBlocks or grid or whatever. Those weak references collection could be for example std::set<std::weak_ptr<Block>>.
Now when removing an element from the grid or allBlocks, you need to remove it from the blocks. To do the lookup on it, you'd need something like this:
struct null_deleter {
void operator()(void const *) const { }
};
To properly create a value for the set lookup. Then, when iterating over any other container, you'd need to use ptr.expired() on the weak_ptr reference in order to see if it was deleted previously.
The caveat of that idea is that the original shared_ptr isn't shared; the class is used just for convenience of weak_ptr and automatic destruction.
std::unique_ptr ownership and int reference
Another, perhaps simpler way is to use std::unordered_map and create a "unique ID" key for each block.
std::unordered_map<unsigned, std::unique_ptr<Block>> blocks;
Now your containers need to be std::set<unsigned>, and the lookup would look like:
for (auto b : grid) {
auto bIt = blocks.find(b);
if (bIt != blocks.end) {
// do things with *bIt
} else {
// e.g. add the b to the "delete list"
}
}
Now you could process your "delete list" and remove the dead ids from the container.
Wrapping up
Since this might get tedious to use, a nice idea could be to wrap the set into a container that would do the cleanup before returning begin() or end() for custom iteration across Block values.
Similarly, the destructor of such wrapped structure could remove the values from the map, thus effectively making all ids in all other containers dangling.
This of course raises an issue of thread safety, because the original blocks map would need to be locked for the whole iteration; at least for modification. Having cbegin()/cend() could allow two threads to read from the same shared map, but ... The kind of problems that arise when sharing data across threads are out of scope for this post, though.
Poisoning
Another idea that came to my mind is sometimes referred to as "poisoning". In this case, you don't need a master container; both of your regular containers would hold shared_ptrs to the Blocks... with a twist.
When a Block is chosen for deletion, a special flag is set on it. It becomes "poisoned", and every container should sweep such blocks before doing iteration.
If every container indeed does so, all references to the Block die and its destructor will fire properly. You're essentially communicating the command through a special value of it.
If you don't want to modify the Block class, having std::shared_ptr<std::optional<Block>> and nullyfying the optional can work just the same, except the destructor of the Block will run immediately, and not when the last structure decides to do its sweep. This might be better or worse depending on your goals and needs.
Is it legal/proper c++0x to leave an object moved for the purpose of move-construction in a state that can only be destroyed? For instance:
class move_constructible {...};
int main()
{
move_constructible x;
move_constructible y(std::move(x));
// From now on, x can only be destroyed. Any other method will result
// in a fatal error.
}
For the record, I'm trying to wrap in a c++ class a c struct with a pointer member which is always supposed to be pointing to some allocated memory area. All the c library API relies on this assumption. But this requirement prevents to write a truly cheap move constructor, since in order for x to remain a valid object after the move it will need its own allocated memory area. I've written the destructor in such a way that it will first check for NULL pointer before calling the corresponding cleanup function from the c API, so that at least the struct can be safely destroyed after the move.
Yes, the language allows this. In fact it was one of the purposes of move semantics. It is however your responsibility to ensure that no other methods get called and/or provide proper diagnostics. Note, usually you can also use at least the assignment operator to "revive" your variable, such as in the classical example of swapping two values.
See also this question
Let's say my class has a private integer variable called count.
I've already hit a breakpoint in my code. Now before I press continue, I want to make it so the debugger will stop anytime count gets a new value assigned to it.
Besides promoting count to a field and setting a breakpoint on the set method of the field, is there any other way to do this?
What you're looking for is not possible in managed code. In C++ this is known as data break point. It allows you to break whenever a block of memory is altered by the running program. But this is only available in pure native C++ code.
A short version of why this is not implemented is that it's much harder in managed code. Native code is nice and predictable. You create memory and it doesn't move around unless you create a new object (or explicitly copy memory).
Managed code is much more complex because it's a garbage collected language. The CLR commonly moves objects around in memory. Therefore simply watching a bit of memory is not good enough. It requires GC interaction.
This is just one of the issues with implementing managed break points.
I assume you're trying to do this because you want to see where the change in value came from. You already stated the way I've always done it: create a property, and break on the set accessor (except that you must then always use that set accessor for this to work).
Basically, I'd say that since a private field is only storage you can't break on it because the private field isn't a breakable instruction.
The only way I can think do do this, is to right click on the variable, and select "Find all references". Once it finds all the references, you can create a new breakpoint at each point in the code where the variable is assigned a value. This would probable work pretty well, unless you were passing the variable in by reference to another function and changing the value in there. In that case, you'd need some way of watching a specific point in memory to see when it changed. I'm not sure if such a tool exists in VS.
Like ChrisW commented. You can set a 'Data Breakpoint' but only for native (non-managed) code. The garbage collector will move allocated memory blocks around when the garbage collector runs. Thus, data breakpoints are not possible for managed code.
Otherwise, no. You must encapsulate access to your item for which you want to 'break on modify'. Since its a private member already, I suggest following Kibbee's suggestion of setting breakpoints wherever its used.
Besides promoting count to a field and setting a breakpoint on the set method of the field, is there any other way to do this?
Make it a property of a different class, create an instance of the class, and set a breakpoint on the property.
Instead of ...
test()
{
int i = 3;
...etc...
i = 4;
}
... have ...
class Int
{
int m;
internal Int(int i) { m = i; }
internal val { set { m = value; } get { return m; } }
}
test()
{
Int i = new Int(3);
...etc...
i.val = 4;
}
The thing is that, using C#, the actual memory location of everything is being moved continually: and therefore the debugger can't easily use the CPU's 'break on memory access' debugging register, and it's easier for the debugger to, instead, implement a code-location breakpoint.