Read Access Violation From Using Smart Pointers - c++

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.

Related

Proper memory control in gSoap

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.

C++ initializer constantly creating new objects at same memory location

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>());
}

New stops my object working correctly

I've had to completely rewrite this problem as I've found out a lot more about it now.
Background:
My programme is drawing some 3d objects under directx11. I have a class that contains the data, pointers, and functions needed to draw the required 3d objects. Everything was working well. I could create many different 3d objects and draw them wherever I wanted. Great!
Then I needed to put them in a container and into a vector so I didn't have to create each object manually, this was where the trouble started; it would crash 1 time in 5 or so.
Unhandled exception at 0x00C308C1 in SpritesNTextN3D.exe: 0xC0000005: Access violation reading location 0xFFFFFFFF.
It crashed when using vectors and maps. I continued this line of enquiry and tried using a pointer and new:
ThreeD_Cube* threed_cube_p;
threed_cube_p = new ThreeD_Cube;
This also caused it to crash when I ran its draw function.
threed_cube_p->draw(threeD, camera, d3dContext_mp);
However if created as a standard object:
ThreeD_Cube threed_cube_;
The draw function never crashes.
threed_cube_-.draw(threeD, camera, d3dContext_mp);
Likewise, creating a pointer to threed_cube_ works as expected.
Question:
What is new doing that the default constructor isn't. Is there anything I should be looking at to resolve this problem?
It seems you have a good constructor, but bad/insufficient (default) assignment operator and bad/insufficient (default) copy constructor.
Let's see why some parts of your code works but some not:
//threed_cube_vec[0].draw(threeD, camera, d3dContext_); // doesnt work!!!
It tells you what's in threed_cube_vec[0] is a bad/corrupted object.
ThreeD_Cube test = threed_cube_vec[0]; // But, if I copy it...
In this line, (for some reason) firstly the constructor is called, which gives you a good object. Then the "=" is called, partially the object is modified, but the object is still good since it was already good before the "="
ThreeD_Cube* test = &threed_cube_vec[0];
As for a pointer, it is the essentially object threed_cube_vec[0] itself, so still corrupted.
ThreeD_Cube test = threed_cube_vec[0];
vector<ThreeD_Cube> test2;
test2.push_back(test);
test2[0].draw(threeD, camera, d3dContext_);
This does not fixed the problem as you said. "test" is a good object, but when you push_back(test) into test2, a copy is pushed back [if you change it to test2.push_back(std::move(test) , the problem could be gone]. Since the copy constructor is incomplete, the object in test2[0] is corrupted. Similar scenario happens with your map.
Conclusion: if an object is originated from the constructor, you get a good object; if an object is originated from a copy constructor, it is corrupted.
A quick test you can do: resize your vector after you declare it, the error should be gone temporarily.
Crash after m = XMMatrixIdentity() - aligment memory in classes?
This topic covers the answer to my problem. I eventually tracked it down to XMMATRIX causing crashes with new due to memory alignment.
Here's a shortened version of the problem:
void matrix_test_pointer()
{
XMMATRIX* xmmatrix_p;
xmmatrix_p = new XMMATRIX;
*xmmatrix_p = XMMatrixIdentity(); // this is where it crashes
}
void matrix_test()
{
XMMATRIX xmmatrix;
xmmatrix = XMMatrixIdentity();
}
int main()
{
string wait;
matrix_test();
cout << "matrix_test() completed.\n";
matrix_test_pointer();
cout << "matrix_test_pointer() completed.\n"; // If it does you are lucky :)
cin >> wait;
return 0;
}
Chances are matrix_test will complete but it will crash before pointer will complete.

Feed a QList with another

hi i'm trying to send a QList as a parameter to another class but for some reason i got a read access violation...
CompareTimeChannel.h
class CompareTimeChannel : public IDataChannel
public:
// #brief The method used to receive the list
void setData(const QList< QSharedPointer<core::ITrackSection> > & sections);
// #brief The list
QList< QSharedPointer<core::ITrackSection> > _sections;
};
CompareTimeChannel.cpp
// #brief Empty constructor
CompareTimeChannel::CompareTimeChannel()
{
}
void CompareTimeChannel::setData(const QList< QSharedPointer<core::ITrackSection> > & sections)
{
//_sections = *new QList< QSharedPointer<core::ITrackSection> > ();
_sections.clear();
_sections.append(sections);
}
Running this code will throw Exception at 0x31cc78d, code: 0xc0000005: read access violation at: 0x4, flags=0x0 on _sections.clear();
I tried to initialize the list before (the commented line _sections = *new QList<...>) but the exception is thrown the same.
An answer would be very appreciated...
EDIT
Ok it's fixed!
First, like #AndreasT said, i had to initialize the default QList constructor.
Then, according to #10WaRRioR01 's answer, the issue comes from CompareTimeChannel which wasn't initialized the first time the method was called. Fixed using :
CompareTimeChannel* chan = static_cast<CompareTimeChannel*>(channel);
Q_ASSERT(chan);
if (chan) {
chan->setData(sections);
}
else {
qDebug() << "Dynamic cast failure";
}
Thank you all, guys!
//_sections = *new QList< QSharedPointer<core::ITrackSection> > ();
You shouldn't ever do something like this. This creates a new instance of QList on the heap and it will never be deleted, so you have a memory leak
You should have done
_sections = QList< QSharedPointer<core::ITrackSection> > ();
instead, and it would be legal. But the most simple way is to use a copy assignment like this
_sections = sections
The problem you got is most likely related to the data you have in _sections. Maybe you are calling your methods on a null CompareTimeChannel object
You should initialize sections in the constructor.
The commented line is just horribly wrong.
new constructs the List on the heap, then you dereference that with *new and the assignment implicitly calls the copy constructor of the new list on the Heap and copies that into the instance. The thing on the heap is still aruond though, so you just created a memory leak.
// #brief Empty constructor
CompareTimeChannel::CompareTimeChannel()
:_sections() // initialization default constructor.
{
}
Edit regarding the comment:
The QList.clear() method calls the destructors of every element of the list. At least one of your shared pointers seems not to be initialized correctly. If you need more info, please paste the code that puts stuff into _sections.
Edit Regarding the exception:
As I said the problem is most likely with the shared pointers not being set to anything interesting. When the SP gets destroyed it calls the destructor of its content, which must exist, otherwise it throws a read access violation, which would explain the symptoms.
This what you showed should work. Your problem is in some other place.
This kind of problems might be caused by many different mistakes, like: bad static_cast or bad c-style cast, break in binary compatibility when you are using dynamic libraries, write outside of table, problems with compiler cache (this happens is quite often so cure for that is below).
First what I would try to do:
make clean
qmake
make
This fixes such problem quite often. if i doesn't help you have to find other problems in your code.

Pointer object in C++

I have a very simple class that looks as follows:
class CHeader
{
public:
CHeader();
~CHeader();
void SetCommand( const unsigned char cmd );
void SetFlag( const unsigned char flag );
public:
unsigned char iHeader[32];
};
void CHeader::SetCommand( const unsigned char cmd )
{
iHeader[0] = cmd;
}
void CHeader::SetFlag( const unsigned char flag )
{
iHeader[1] = flag;
}
Then, I have a method which takes a pointer to CHeader as input and looks
as follows:
void updateHeader(CHeader *Hdr)
{
unsigned char cmd = 'A';
unsigned char flag = 'B';
Hdr->SetCommand(cmd);
Hdr->SetFlag(flag);
...
}
Basically, this method simply sets some array values to a certain value.
Afterwards, I create then a pointer to an object of class CHeader and pass it to
the updateHeader function:
CHeader* hdr = new CHeader();
updateHeader(hdr);
In doing this, the program crashes as soon as it executes the Hdr->SetCommand(cmd)
line. Anyone sees the problem, any input would be really appreciated
When you run into a crash, act like a crime investigator: investigate the crime scene.
what is the information you get from your environment (access violation? any debug messages? what does the memory at *Hdr look like? ...)
Is the passed-in Hdr pointer valid?
Then use logical deduction, e.g.:
the dereferencing of Hdr causes an access violation
=> passed in Hdr points to invalid memory
=> either memory wasn't valid to start with (wrong pointer passed in), or memory was invalidated (object was deleted before passing in the pointer, or someone painted over the memory)
...
It's probably SEGFAULTing. Check the pointers.
After
your adding some source code
your comment that the thing runs on another machine
the fact that you use the term 'flag' and 'cmd' and some very small datatypes
making me assume the target machine is quite limited in capacity, I suggest testing the result of the new CHeader for validity: if the system runs out of resources, the resulting pointer will not refer to valid memory.
There is nothing wrong with the code you've provided.
Are you sure the pointer you've created is the same same address once you enter the 'updateHeader' function? Just to be sure, after new() note the address, fill the memory, sizeof(CHeader), with something you know is unique like 0XDEAD, then trace into the updateHeader function, making sure everything is equal.
Other than that, I wonder if it is an alignment issues. I know you're using 8 bit values, but try changing your array to unsigned ints or longs and see if you get the same issue. What architecture are you running this on?
Your code looks fine. The only potential issue I can see is that you have declared a CHeader constructor and destructor in your class, but do not show the implementation of either. I guess you have just omitted to show these, else the linker should have complained (if I duplicate this project in VC++6 it comes up with an 'unresolved external' error for the constructor. It should also have shown the same error for the destructor if you had a... delete hdr; ...statement in your code).
But it is actually not necessary to have an implementation for every method declared in a class unless the methods are actually going to get called (any unimplemented methods are simply ignored by the compiler/linker if never called). Of course, in the case of an object one of the constructor(s) has to be called when the object is instantiated - which is the reason the compiler will create a default constructor for you if you omit to add any constructors to your class. But it will be a serious error for your compiler to compile/link the above code without the implementation of your declared constructor, so I will really be surprised if this is the reason for your problem.
But the symptoms you describe definitely sounds like the 'hdr' pointer you are passing to the updateHeader function is invalid. The reason being that the 1st time you are dereferencing this pointer after the updateHeader function call is in the... Hdr->SetCommand(cmd); ...call (which you say crashes).
I can only think of 2 possible scenarios for this invalid pointer:
a.) You have some problem with your heap and the allocation of memory with the 'new' operator failed on creation of the 'hdr' object. Maybe you have insufficient heap space. On some embedded environments you may also need to provide 'custom' versions of the 'new' and 'delete' operator. The easiest way to check this (and you should always do) is to check the validity of the pointer after the allocation:
CHeader* hdr = new CHeader();
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
The normal behaviour when 'new' fails should actually be to throw an exception - so the following code will cater for that as well:
try{
CHeader* hdr = new CHeader();
} catch(...) {
//handle or throw specific exception i.e. AfxThrowMemoryException() for MFC
}
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
}
b.) You are using some older (possibly 16 bit and/or embedded) environment, where you may need to use a FAR pointer (which includes the SEGMENT address) for objects created on the heap.
I suspect that you will need to provide more details of your environment plus compiler to get any useful feedback on this problem.