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>
Related
I'm considering using V8 as an embedded JavaScript engine for a project but I'm having trouble figuring out how to manage the lifetime of native C++ objects. This experiment was supposed to demonstrate the Weak Pointer callback.
Near the end of the code below I call v8::Persistent::SetWeak and install a callback. All I want is to be able to create a demonstration of this callback being called.
I half-heartedly hoped it would be as easy as letting the handles fall out of scope, but the code below doesn't call the callback. I also read somewhere that calling Isolate::IdleNotificationDeadline might force a garbage collection, but this didn't work either.
How can I demonstrate the weak pointer callback being called? I'd like to write some code that will result in the the cleanup function being called at some point before the program exits.
I clearly am having trouble understanding how to set this up properly and would appreciate some assistance an an explanation. I'm afraid I just don't get it yet.
My expectation is that it's possible to create a Weak Pointer via a Persistent handle and that when there are no more handles to an object, the callback will (eventually) be called so that native C++ resources associated with that JavaScript object can be freed.
I'm particularly put off by a comment in the v8.h header file:
NOTE: There is no guarantee as to when or even if the callback is invoked. The invocation is performed solely on a best effort basis. As always, GC-based finalization should not be relied upon for any critical form of resource management!
This makes the entire engine seem useless to me for managing a native object with this mechanism. But I'm confident there's at least some minimal contrived scenario in which the callback is called.
My requirement is that I am able to write some JavaScript to allocate an object that will eventually be freed when there are no more references to it.
foo = createFoo(); // creates a JavaScript object wrapping the native C++ Foo object.
doSomethingWith(foo); // do stuff with the Foo here
foo = null; // make sure there are no more JavaScript handles to the wrapper for the Foo object.
// After this point, I'm hoping V8 will eventually let me know that I can delete the native C++ Foo object
I'm assuming I don't actually have to execute any JavaScript to demonstrate the weak pointer and cleanup mechanism. I was hoping I could just create a Persistent handle and install the Weak callback then let it go out of scope. I seem to be wrong in that assumption, or I have failed to demonstrate it here.
#include <iostream>
#include "include/libplatform/libplatform.h"
#include "include/v8.h"
class Foo {};
void cleanup(const v8::WeakCallbackInfo<Foo>& data)
{
std::cout << "Weak Callback called" << std::endl;
delete data.GetParameter();
}
int main(int argc, char* argv[]) {
std::cout << "Start..." << std::endl;
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
// Create a new isolate and make it the current one
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, v8::ObjectTemplate::New(isolate));
v8::Context::Scope context_scope(context);
v8::Local<v8::Object> obj = v8::ObjectTemplate::New(isolate)->NewInstance(context).ToLocalChecked();
v8::Persistent<v8::Object> persistent;
persistent.Reset(isolate, obj);
persistent.SetWeak(new Foo(), cleanup, v8::WeakCallbackType::kParameter);
}
isolate->IdleNotificationDeadline(1.0);
std::cout << "...Finish" << std::endl;
}
Note: The above code example should be built the same way the hello_world example for V8 is built.
For a contrived example, calling isolate->LowMemoryNotification() should do the trick. I wouldn't recommend doing that in production though, as it's a huge waste of CPU time (unless you really have a low memory situation where you're close to crashing due to OOM).
Apart from that, the comment you found holds. Relying on weak callbacks to free objects is fine; relying on it for managing critical and scarce resources is not recommended. If the objects in question add up to significant size, you should use isolate->AdjustAmountOfExternalAllocatedMemory(...) as appropriate, to let the GC know that there is something to be freed. And you should have your own fallback mechanism to clean up everything when the Isolate goes away (if you're not terminating the entire process then anyway).
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.
I have a class exposing through it's interface add function:
void AddObject(Object *o);
Inside the class I maintain the objects in set<shared_ptr<Object>>.
Since I will create shared_ptr from the received pointer I thought to limit the function argument to only rvalue pointers so to make sure that the user will not delete the pointer I use. And so I'll change the function declaration to:
void AddObject(Object* &&o);
so a typical use will be:
AddObject(new Object())
preventing the user to accidentally delete pointer I hold.
I don't want to to use shared_ptr in the interface because the user is not familiar with shared_ptr.
Do you think my suggestion is a good idea?
I think this is a bad idea. I'm sure there is a reason why shared_ptr c-tor that gets a raw pointer is marked explicit instead of using r-value. In my eyes, It's better to teach the users once about smart pointers or at least teach them about using make_shared/make_unique (which are safer and, in the case of make_shared, more efficient, BTW).
BTW, why shared_ptr and not unique_ptr?
Also, why set? Even if you want to make sure you hold each pointer only once and searching a vector each time doesn't look natural enough in your code, I don't see a reason to hold the pointers sorted instead of using unordered_set.
First of all, this approach will not prevent the user from deleting the pointer. Consider this example
auto obj = new Object();
AddObject(std::move(obj));
delete obj;
Secondly, the amount of steps between calling new and the creation of shared_ptr should be as few as possible. If anything happens inside AddObject before it can create a shared_ptr, the object will never get deleted.
The same applies if there are more arguments to AddObject(). If constructing those fails, you will leak memory.
void AddObject(Object* &&o, SomeOtherObject* x);
AddObject(new Object(), xx()); // if xx() throws, memory leak will occur
Ideally you would "wrap" object creating into shared_ptr construction:
void AddObject(std::shared_ptr<Object> o);
AddObject(std::make_shared<Object>());
Either of the following methods may solve your problem.
You may append more comments for AddObject to tell users that delete the pointer they added is not allowed. This is almost enough.
Or, you could also make Object inherits from a base class which has a private destructor and a method named destroyByOwner.
I am extremely confused about resource management in C++/CLI. I thought I had a handle (no pun intended) on it, but I stumbled across the auto_gcroot<T> class while looking through header files, which led to a google search, then the better part of day reading documentation, and now confusion. So I figured I'd turn to the community.
My questions concern the difference between auto_handle/stack semantics, and auto_gcroot/gcroot.
auto_handle: My understanding is that this will clean up a managed object created in a managed function. My confusion is that isn't the garbage collector supposed to do that for us? Wasn't that the whole point of managed code? To be more specific:
//Everything that follows is managed code
void WillThisLeak(void)
{
String ^str = gcnew String ^();
//Did I just leak memory? Or will GC clean this up? what if an exception is thrown?
}
void NotGoingToLeak(void)
{
String ^str = gcnew String^();
delete str;
//Guaranteed not to leak, but is this necessary?
}
void AlsoNotGoingToLeak(void)
{
auto_handle<String ^> str = gcnew String^();
//Also Guaranteed not to leak, but is this necessary?
}
void DidntEvenKnowICouldDoThisUntilToday(void)
{
String str();
//Also Guaranteed not to leak, but is this necessary?
}
Now this would make sense to me if it was a replacement for the C# using keyword, and it was only recommended for use with resource-intensive types like Bitmap, but this isnt mentioned anywhere in the docs so im afraid ive been leaking memory this whole time now
auto_gcroot
Can I pass it as an argument to a native function? What will happen on copy?
void function(void)
{
auto_gcroot<Bitmap ^> bmp = //load bitmap from somewhere
manipulateBmp(bmp);
pictureBox.Image = bmp; //Is my Bitmap now disposed of by auto_gcroot?
}
#pragma unmanaged
void maipulateBmp(auto_gcroot<Bitmap ^> bmp)
{
//Do stuff to bmp
//destructor for bmp is now called right? does this call dispose?
}
Would this have worked if I'd used a gcroot instead?
Furthermore, what is the advantage to having auto_handle and auto_gcroot? It seems like they do similar things.
I must be misunderstanding something for this to make so little sense, so a good explanation would be great. Also any guidance regarding the proper use of these types, places where I can go to learn this stuff, and any more good practices/places I can find them would be greatly appreciated.
thanks a lot,
Max
Remember delete called on managed object is akin to calling Dispose in C#. So you are right, that auto_handle lets you do what you would do with the using statement in C#. It ensures that delete gets called at the end of the scope. So, no, you're not leaking managed memory if you don't use auto_handle (the garbage collector takes care of that), you are just failing to call Dispose. there is no need for using auto_handle if the types your dealing with do not implement IDisposable.
gcroot is used when you want to hold on to a managed type inside a native class. You can't just declare a manged type directly in a native type using the hat ^ symbol. You must use a gcroot. This is a "garbage collected root". So, while the gcroot (a native object) lives, the garbage collector cannot collect this object. When the gcroot is destroyed, it lets go of the reference, and the garbage collector is free to collect the object (assuming it has no other references). You declare a free-standing gcroot in a method like you've done above--just use the hat ^ syntax whenever you can.
So when would you use auto_gcroot? It would be used when you need to hold on to a manged type inside a native class AND that managed type happens to implement IDisposable. On destruction of the auto_gcroot, it will do 2 things: call delete on the managed type (think of this as a Dispose call--no memory is freed) and free the reference (so the type can be garbage collected).
Hope it helps!
Some references:
http://msdn.microsoft.com/en-us/library/aa730837(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/481fa11f(v=vs.80).aspx
http://www.codeproject.com/Articles/14520/C-CLI-Library-classes-for-interop-scenarios
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