I have a simple recursive-type container object "Level" (such as a directory, which can contain multiples of itself), although I'm not sure that's related to this problem.
//Level.h
class Level
{
public:
Level();
vector<Level*> SubLevels;
Level CreateSubLevel();
}
//Level.cpp
Level::Level()
{
SubLevels = vector<Level*>();
}
Level Level::CreateSubLevel()
{
Level NewLevel = Level();
SubLevels.push_back(&NewLevel);
return NewLevel;
}
If then in my main loop I call
//main.cpp
Level MasterLevel = Level();
MasterLevel.CreateSubLevel();
MasterLevel.CreateSubLevel();
MasterLevel.CreateSubLevel();
I find that indeed the vector MasterLevel.SubLevels contains three pointers to Level objects. However, they are all pointers to the same address!
I'm not sure why this is happening. My memory management skills are lacking - but I'm suspecting that it's because every time CreateSubLevel() is called, a new object is created, but then it is deleted when CreateSubLevel() exits? I thought that ARC would keep track of the fact that the pointer to it still exists, but perhaps I'm mistaken? Or is it another issue entirely?
How can I best fix this problem?
Thanks!
SubLevels is holding onto three pointers to temporaries. It's not a surprise that the compiler chose to reuse the same memory for the temporary each time - why not?
If you want to actually store three different Levels correctly, you will either have to store them by value:
vector<Level> SubLevels;
SubLevels.push_back(Level());
Or actually allocate Levels:
vector<Level*> SubLevels;
SubLevels.push_back(new Level); // don't forget to delete!
The reason you come up with the same value every time is because you are using the address of a temporary variable (on the stack). Every time the function CreateSubLevel() is called, the stack is reused, thus the objects are stored in the same location every call.
You can allocate objects on the heap using operator new():
vector<Level*> SubLevels;
SubLevels.push_back(new Level);
Then you can delete them in a destructor:
Level::~Level()
{
vector<Level*>::iterator i;
for (i = SubLevels.begin(); i != SubLevels.end(); ++i)
delete *i;
}
You have three calls to MasterLevel.CreateSubLevel(); one after the other. Each call creates a stack frame that is of the same size. Hence, the address of the local variable is the same. You are storing the address of the local variable in SubLevels.
If you use the address stored in SubLevels, you will run into undefined behavior. You need to allocate memory from heap.
While you are at it, keep a list of smart pointers, std::unique_ptr or std::shared_ptr instead of storing raw pointers.
Use
vector<std::shared_ptr<Level>> SubLevels;
and use it as:
void Level::CreateSubLevel()
{
SubLevels.push_back(std::make_shared<Level>());
}
Related
This problem has bugged me for several days now, and I just cant figure it out. What I am trying to do is get an Entity from the entityMap and make a copy of it. An Entity is essentialy a map of components, so I looped through each component and made a copy of it. I debugged the program, and it worked fine until the very last line, where it said "read access violation this was 0xFFFFFFFFFFFFFFF7." It was very strange as everything was initialized (I checked the debugger)
if (entityMap.find(classname) != entityMap.end()) {
std::shared_ptr<Entity> & prefab = entityMap[classname];
std::shared_ptr<Entity> entity = std::shared_ptr<Entity>(new Entity());
for (auto & component : prefab->GetComponentMap()) {
Component * compPtr = component.second.get();
std::cout << compPtr->GetMemorySize() << "\n";
size_t size = sizeof(compPtr->GetMemorySize());
void * buffer = operator new(size);
memcpy(buffer, compPtr, size);
std::shared_ptr<Component> newComponent = std::shared_ptr<Component>(reinterpret_cast<Component *>(buffer));
entity->AddComponent(newComponent);
newComponent->SetOwner(entity);
}
Here is the offending line
newComponent->SetOwner(entity);
Here is all it does, setting the owner instance variable to the passed in parameter. That was where the debugger complained and sent me to file "memory" at _Decref method.
void Component::SetOwner(std::shared_ptr<Entity> owner) {
this->owner = owner;
}
The problem here is that you can’t copy objects just by copying the memory. For basic plain data objects without any constructors, destructors, or pointers this may work but for anything more complex it most likely won’t.
For example, if the object contains pointers to data and these are released in a destructor then the data is not deep copied, rather the pointer is, and you get double free and also possible pointers to unallocated memory. If the object relies on something being done in the constructor it is never done when copying memory. And depending on how the size is calculated it may not even be a complete copy.
This is why you should always provide a cloning mechanism in the class that takes care of these issues in a way that suits the object and makes sure there’s proper deep/shallow copying depending on the contents.
I'm currently developing application using gSoap library and has some misunderstanding of proper usage library. I has generated proxy object (-j flag) which wrapped my own classes, as you can see below. Application must work 24/7 and connect simultaneously to many cameras (~50 cameras), so after every request i need to clear all temporary data. Is it normal usage to call soap_destroy() and soap_end() after every request? Because it seem's overkill to do it after each request. May be exists another option of proper usage?
DeviceBindingProxy::destroy()
{
soap_destroy(this->soap);
soap_end(this->soap);
}
class OnvifDeviceService : public Domain::IDeviceService
{
public:
OnvifDeviceService()
: m_deviceProxy(new DeviceBindingProxy)
{
soap_register_plugin(m_deviceProxy->soap, soap_wsse);
}
int OnvifDeviceService::getDeviceInformation(const Access::Domain::Endpoint &endpoint, Domain::DeviceInformation *information)
{
_tds__GetDeviceInformation tds__GetDeviceInformation;
_tds__GetDeviceInformationResponse tds__GetDeviceInformationResponse;
setupUserPasswordToProxy(endpoint);
m_deviceProxy->soap_endpoint = endpoint.endpoint().c_str();
int result = m_deviceProxy->GetDeviceInformation(&tds__GetDeviceInformation, tds__GetDeviceInformationResponse);
m_deviceProxy->soap_endpoint = NULL;
if (result != SOAP_OK) {
Common::Infrastructure::printSoapError("Fail to get device information.", m_deviceProxy->soap);
m_deviceProxy->destroy();
return -1;
}
*information = Domain::DeviceInformation(tds__GetDeviceInformationResponse.Manufacturer,
tds__GetDeviceInformationResponse.Model,
tds__GetDeviceInformationResponse.FirmwareVersion);
m_deviceProxy->destroy();
return 0;
}
}
To ensure proper allocation and deallocation of managed data:
soap_destroy(soap);
soap_end(soap);
You want to do this often to avoid memory to fill up with old data. These calls remove all deserialized data and data you allocated with the soap_new_X() and soap_malloc() functions.
All managed allocations are deleted with soap_destroy() followed by soap_end(). After that, you can start allocating again and delete again, etc.
To allocate managed data:
SomeClass *obj = soap_new_SomeClass(soap);
You can use soap_malloc for raw managed allocation, or to allocate an array of pointers, or a C string:
const char *s = soap_malloc(soap, 100);
Remember that malloc is not safe in C++. Better is to allocate std::string with:
std::string *s = soap_new_std__string(soap);
Arrays can be allocated with the second parameter, e.g. an array of 10 strings:
std::string *s = soap_new_std__string(soap, 10);
If you want to preserve data that otherwise gets deleted with these calls, use:
soap_unlink(soap, obj);
Now obj can be removed later with delete obj. But be aware that all pointer members in obj that point to managed data have become invalid after soap_destroy() and soap_end(). So you may have to invoke soap_unlink() on these members or risk dangling pointers.
A new cool feature of gSOAP is to generate deep copy and delete function for any data structures automatically, which saves a HUGE amount of coding time:
SomeClass *otherobj = soap_dup_SomeClass(NULL, obj);
This duplicates obj to unmanaged heap space. This is a deep copy that checks for cycles in the object graph and removes such cycles to avoid deletion issues. You can also duplicate the whole (cyclic) managed object to another context by using soap instead of NULL for the first argument of soap_dup_SomeClass.
To deep delete:
soap_del_SomeClass(obj);
This deletes obj but also the data pointed to by its members, and so on.
To use the soap_dup_X and soap_del_X functions use soapcpp2 with options -Ec and -Ed, respectively.
In principle, static and stack-allocated data can be serialized just as well. But consider using the managed heap instead.
See https://www.genivia.com/doc/databinding/html/index.html#memory2 for more details and examples.
Hope this helps.
The way memory has to be handled is described in Section 9.3 of the GSoap documentation.
I have this for loop that iterates through a vector.
Then it checks if the given name equals the name of the model.
Finally it creates a pointer and returns it. Now my question is if there is going to be any memory leak if i don't delete the pointer?
Model3D* ModelMemory::GetModel(char* name)
{
for (std::vector<Model3D*>::reverse_iterator it = mModels->rbegin();it != mModel->rend();it++)
{
Model3D *model = *it;
if (model->GetName() == name)
{
return model;
}
}
}
Thanks for your help!
--EDIT--
So my goal here is to store all my 3d models (stored in Model3D classes) in a vector,
so that i can retrieve it later using the name of the Model3D.
Is there maybe a better way to do this? Because it seems like my way is not really good programming...
No, there wont be memory leakage, of course if you delete all models later. Also, use strcmp() to compare two strings
You are not dynamically allocating any memory. This is static allocation
Model3D *model = *it;
and it will be destroyed when the context block of this variable ends (i.e. when you return from this method). It's only statically allocated pointer.
Dynamically allocation is done with the new operator and there isn't any.
Simple rule to check for leaks is to have delete for every new.
You can check your memory leaks with valgrind terminal tool.
I recently started with C++ and i'm not entirely sure I grasp the concept of pointers and their connection to arrays. I have two classes, Term and Polynom. I have a main loop which allows the user to enter 2 numbers. Those numbers is then added to the "Term" object and that object is then added to the "Polynom" object. Everytime the loop is executed a new "Term" object is created.
//These lines are executed until the user is done entering numbers
potens = new Term;
potens->sattPotens(kinput, ninput);//Add values to "Term object"
poly.addTerm(potens);//Add "Term" object to "Polynom" object
A "Polynom" object is only created once in the program. In the "Polynom" class I use a "Term" pointer to store all the "Term" objects that is added to the "Polynom" object. The "Term" pointer in the "Polynom" class is initiated once in the "Polynom" constructor.
void Polynom::addTerm(Term *t){
*(term+antal_termer) = *t;//This is were the program crashes
antal_termer++;
}
I know I could use a vector instead of a pointer to store the "Term" objects but i'm trying to learn how pointers work. I am also unsure when I'm supposed to delete the objects created in the main loop. Since every time the loop is executed I create a new "Term" object but I never delete them.
EDIT: I used to allocate the "Term" object in the "Polynom" class this way: term = new Term[]; I then changed it to term = new Term[10]; but I still crashes when I execute term[antal_termer] = *t;
*(term+antal_termer) = *t;//This is were the program crashes
antal_termer++;
This crashes because you probably haven't allocated enough memory. Your best choice is to use a std::vector instead of a dynamic array.
Is term allocated term = new Term; or term = new Term[sz];?
If it's the first, you can only store one object, and term+antal_termer goes beyond that. If it's the second, you run into problems if antal_termer >= sz.
The std::vector option gives you automatic management:
std::vector<Term> terms;
Term potens; //why use new?
terms.push_back(potens);
Note that I'm using objects, not pointers. For pointers, it'd be
std::vector<Term*> terms;
Term* potens = new Term;
terms.push_back(potens);
But note that you have to delete the memory when you're done with it.
Pasting in outcome from comments.
antal_termer was not initialised in the constructor, resulting in invalid memory access here:
*(term+antal_termer) = *t;
As the code is copying t, via assignment, you can delete potens; after the call to addTerm(). The code must prevent going beyond the end of the term array in addTerm(), otherwise another invalid memory access will occur:
void Polynom::addTerm(Term *t){
if (antal_termer < 10) // Use constant instead of literal 10
{
*(term+antal_termer) = *t;
antal_termer++;
}
}
I have a code that has a large number of mallocs and device-specific API mallocs (I'm programming on a GPU, so cudaMalloc).
Basically my end of my beginning of my code is a big smorgasbord of allocation calls, while my closing section is deallocation calls.
As I've encapsulated my global data in structures, the deallocations are quite long, but at least I can break them into a separate function. On the other hand, I would like a shorter solution. Additionally an automatic deallocator would reduce the risk of memory leaks created if I forget to explicitly write the deallocation in the global allocator function.
I was wondering whether it'd be possible to write some sort of templated class wrapper that can allow me to "register" variables during the malloc/cudaMalloc process, and then at the end of simulation do a mass loop-based deallocation (deregistration). To be clear I don't want to type out individual deallocations (free/cudaFrees), because again this is long and undesirable, and the assumption would be that anything I register won't be deallocated until the device simulation is complete and main is terminating.
A benefit here is that if I register a new simulation duration variable, it will automatically deallocate, so there's no danger of me forgetting do deallocate it and creating a memory leak.
Is such a wrapper possible?
Would you suggest doing it?
If so, how?
Thanks in advance!
An idea:
Create both functions, one that allocates memory and provides valid pointers after register them in a "list" of allocated pointers. In the second method, loop this list and deallocate all pointers:
// ask for new allocated pointer that will be registered automatically in list of pointers.
pointer1 = allocatePointer(size, listOfPointers);
pointer2 = allocatePointer(size, listOfPointers);
...
// deallocate all pointers
deallocatePointers(listOfPointers);
Even, you may use different listOfPointers depending of your simulation scope:
listOfPointer1 = getNewListOfPointers();
listOfPointer2 = getNewListOfPointers();
....
p1 = allocatePointer(size, listOfPointer1);
p2 = allocatePointer(size, listOfPointer2);
...
deallocatePointers(listOfPointers1);
...
deallocatePointers(listOfPointers2);
There are many ways to skin a cat, as they say.
I would recommend thrust's device_vector as a memory management tool. It abstracts allocation, deallocation, and memcpy in CUDA. It also gives you access to all the algorithms that Thrust provides.
I wouldn't recommend keeping random lists of unrelated pointers as Tio Pepe recommends. Instead you should encapsulate related data into a class. Even if you use thrust::device_vector you may want to encapsulate multiple related vectors and operations on them into a class.
The best choice is probably to use the smart pointers from C++ boost library, if that is an option.
If not, the best you can hope for in C is a program design that allows you to write allocation and deallocation in one place. Perhaps something like the following pseudo code:
while(!terminate_program)
{
switch(state_machine)
{
case STATE_PREOPERATIONAL:
myclass_init(); // only necessary for non-global/static objects
myclass_mem_manager();
state_machine = STATE_RUNNING;
break;
case STATE_RUNNING:
myclass_do_stuff();
...
break;
...
case STATE_EXIT:
myclass_mem_manager();
terminate_program = true;
break;
}
void myclass_init()
{
ptr_x = NULL;
ptr_y = NULL;
/* Where ptr_x, ptr_y are some of the many objects to allocate/deallocate.
If ptr is a global/static, (static storage duration) it is
already set to NULL automatically and this function isn't
necessary */
}
void myclass_mem_manager()
{
ptr_x = mem_manage (ptr_x, items_x*sizeof(Type_x));
ptr_y = mem_manage (ptr_y, items_y*sizeof(Type_y));
}
static void* mem_manage (const void* ptr, size_t bytes_n)
{
if(ptr == NULL)
{
ptr = malloc(bytes_n);
if (ptr == NULL)
{} // error handling
}
else
{
free(ptr);
ptr = NULL;
}
return ptr;
}