I have a memory corruption in my program. The driver_s2lp::_conf.rxtx object gets corrupted, after a while (involving some new and delete) in my program.
class driver_s2lp
{
public:
struct conf
{
std::function<std::vector<uint8_t>(std::vector<uint8_t> &data, size_t len)> rxtx;
//there are other variables here
};
driver_s2lp::driver_s2lp(conf config)
{
_conf = config;
}
private:
conf _conf;
};
class s2lp_custom_ikm : private driver_s2lp
{
struct conf
{
std::function<std::vector<uint8_t>(std::vector<uint8_t> &data, size_t len)> rxtx;
//there are other variables here
};
/* can I safely copy the std::function like this ? */
s2lp_custom_ikm(conf configuration) : driver_s2lp([configuration]() {
struct driver_s2lp::conf driver_conf;
driver_conf.rxtx = configuration.rxtx;
// other copies here
return driver_conf;
}())
{
this->configuration = configuration;
}
void do_something()
{
// it seems that driver_s2lp::_conf.rxtx can be broken here
}
};
int main()
{
s2lp_custom_ikm::conf s2lp_config;
s2lp_config.debug = [](std::string s) { printf("%s",s.c_str()); };
//other std::functions here
s2lp = new s2lp_custom_ikm(s2lp_config);
s2lp->do_something()
while(1){};
}
I wonder if there is something wrong with copying std::function as I do in the constructor of the s2lp_custom_ikm class?
I'm not sure it is relevant but it is the m_invoker which gets corrupted in the std::function object when I add a watchpoint in the debugger.
The problem may be somewhere else but I want to be sure the copy is not the source of the problem.
I wonder if there is something wrong with copying std::function as I do in the constructor of the s2lp_custom_ikm class?
No.
The std::function copies in your constructor (both the initialiser and the body) are safe.
The program snippet shown does not contain a bug capable of the symptoms you report.
Related
I was trying to write a sample code for implementing shared pointer [just for practice].
In this following example,
why compiler is not complaining about modifying other_T
And why copy constructor SharedPtr(const T& other_T) is not getting called ?
Here is the code snippet.
#include <iostream>
using namespace std;
#define DBG cout<<"[DEBUG]"<<__PRETTY_FUNCTION__<<endl
class RefCount
{
protected:
int m_ref;
RefCount(){ DBG; m_ref = 1 ; }
void reference(){ DBG; ++m_ref; }
void dereference(){ DBG;--m_ref; }
};
template <class T>
class SharedPtr : public RefCount
{
T* m_T;
public:
SharedPtr() { DBG; m_T = new T; }
SharedPtr(const T& other_T){
DBG;
m_T = other_T.m_T;
other_T.dereference();
other_T.m_T = NULL;
}
~SharedPtr() {
DBG;
dereference();
cout<<m_ref<<endl;
if(m_ref <= 0 && m_T != NULL ){
cout<<"Destroying"<<endl;
delete m_T;
m_T = NULL;
}
}
};
class A{};
int main()
{
SharedPtr<A> obj;
cout<<"assigning "<<endl;
SharedPtr<A> obj2 = obj;
cout<<"END"<<endl;
return 0;
}
and the result is segfault.
Your primary problem is that the copy constructor is being called--but you haven't defined a copy constructor, so you're getting the copy constructor that's defined by the compiler by default.
That copy constructor just does a member-wise copy. That means you've allocated one A with new, then pointed two SharedPtr objects at that same A. The first one to get destroyed deletes the A object. Then the second one gets destroyed, attempts to delete the same object again, and havoc ensues.
In the end, it doesn't look to me like much (any?) of this is going to make any real difference though. I'm pretty sure your basic design is broken. To get a working shared pointer, you have one reference count and "raw" pointer to the final object. Then you have N SharedPtr objects referring to that one ref count/pointer structure that in turn refers to the final object.
You're trying to combine the raw pointer/ref count into the individual SharedPtr, and I don't see any way that can actually work.
It also seems to me that the basic concept of what you've called a RefCount is really part of the design of a SharedPtr. As such, I think its definition should be nested inside that of SharedPtr (and probably made private, since the outside world has no reason to know it exists, not to mention being able to access it directly).
With those taken into account, the code might end up something like this:
#include <iostream>
using namespace std;
#define DBG cout<<"[DEBUG]"<<__PRETTY_FUNCTION__<<endl
template <class T>
class SharedPtr {
template <class U>
struct Ref {
mutable int m_ref;
U *data;
Ref(T *data) : m_ref(1), data(data) { DBG; }
void add_ref() const { DBG; ++m_ref; std::cout << "m_ref=" << m_ref << "\n"; }
void sub_ref() const { DBG; --m_ref; std::cout << "m_ref=" << m_ref << "\n"; }
~Ref() { delete data; }
};
Ref<T> *r;
public:
SharedPtr(T *data) { DBG; r = new Ref<T>(data); }
SharedPtr(SharedPtr const &p) : r(p.r) { DBG; r->add_ref(); }
~SharedPtr() {
DBG;
r->sub_ref();
if (0 == r->m_ref) {
delete r;
std::cout << "deleted pointee\n";
}
}
};
class A{};
int main() {
SharedPtr<A> obj(new A);
cout<<"copying "<<endl;
SharedPtr<A> obj2 = obj;
cout<<"END"<<endl;
return 0;
}
Notes: though this fixes at least some of the basic design, it's still quite a ways short of usable. It's missing the dereference operator, so you can't use the pointer to get to the value it points at. It'll break completely in a multi-threaded environment. I haven't thought enough about it to be sure, but my immediate guess is that it's probably not exception safe either.
So, I've got the following Command Pattern implementation, which is contained within a std::map<CString, IWrite*> commandMap:
class IWrite
{
protected:
CStdioFile* fileWriter;
public:
IWrite(CStdioFile* _fileWriter)
: fileWriter(_fileWriter)
{
}
virtual ~IWrite()
{
}
virtual BOOL exec() = 0;
};
class FloatWrite : public IWrite
{
private:
float input;
public:
FloatWrite(CStdioFile* _fileWriter, float _input)
: IWrite(_fileWriter), input(_input)
{
}
BOOL exec()
{
CString fieldvalue;
fieldvalue.Format("%f", input);
fileWriter->WriteString(fieldvalue);
return TRUE;
}
};
The issue I'm having is that my static analysis tool complains that fileWriter is not freed or zeroed in the destructor of IWrite. However, by adding a delete fileWriter in the destructor, I get a memory access error when I delete the Command Pattern object in the map before calling std::map.clear() as below:
// free map memory
for ( std::map<CString, IWrite*>::iterator mapItr = commandMap.begin();
mapItr != commandMap.end();
++mapItr)
{
delete mapItr->second;
}
commandMap.clear();
Am I approaching memory management incorrectly here? I have not done much work with STL maps, so I'm not familiar with an idiomatic approach.
EDIT: How I add elements to the map:
void FooClass::initCommandMap(const MSG_DATA_STRUCT * msgdata)
{
// Write a float, foo
commandMap[_T("foo")] = new FloatWrite(&fileWriter, msgdata->foo);
// Write an unsigned int, bar
commandMap[_T("bar")] = new UIntWrite(&fileWriter, msgdata->bar);
// etc...
}
This is called each time the user chooses to write out the data, so the fileWriter object used by the various exec()'s is current with the file selected by the user.
Note that CStdioFile fileWriter is a member variable of FooClass.
Why do you keep a pointer to fileWriter? From what I see, your Command object assumes that a writer should exist before the command can be used. It also shouldn't try to manage the writer object, since it can be shared by multiple command objects.
Try keeping a reference instead.
class IWrite
{
protected:
CStdioFile &fileWriter;
public:
IWrite(CStdioFile &_fileWriter)
: fileWriter(_fileWriter)
{
}
virtual ~IWrite()
{
}
virtual BOOL exec() = 0;
};
I have a map of addresses that allows me to store arbitrary data with objects. Basically, a library I'm writing has a templated function that winds up storing arbitrary data with objects.
std::map<void *, MyUserData>
This works, until the object passed in is destroyed, leaving its user data in the map. I want the associated user data to be removed as well, so I need to somehow listen for the destructor of the passed in object,
Some example code that illustrates the problem:
#include <map>
#include <memory>
struct MyUserData
{
int someNum;
};
std::map<void *, MyUserData> myMap;
template <typename T>
registerObject<T>(const std::shared_ptr<T> & _object)
{
static inc = 0;
myMap[(void *)&_object->get()].someNum = inc++;
}
struct MyObject
{
int asdf;
};
int main(int _argc, char ** _argv)
{
auto obj = std::make_shared<MyObject>();
obj->asdf = 5;
registerObject(obj);
obj = 0;
//The user data is still there. I want it to be removed at this point.
}
My current solution is to set a custom deleter on the shared_ptr. This signals me for when the object's destructor is called, and tells me when to remove the associated user data. Unfortunately, this requires my library to create the shared_ptr, as there is no "set_deleter" function. It must be initialized in the constructor.
mylib::make_shared<T>(); //Annoying!
I could also have the user manually remove their objects:
mylib::unregister<T>(); //Equally annoying!
My goal is to be able to lazily add objects without any prior-registration.
In a grand summary, I want to detect when the object is deleted, and know when to remove its counterpart from the std::map.
Any suggestions?
P.S. Should I even worry about leaving the user data in the map? What are the chances that an object is allocated with the same address as a previously deleted object? (It would end up receiving the same user data as far as my lib is concerned.)
EDIT: I don't think I expressed my problem very well initially. Rewritten.
From you code example, it looks like the external interface is
template <typename T>
registerObject<T>(const std::shared_ptr<T> & _object);
I assume there is a get-style API somewhere. Let's call this getRegisteredData. (It could be internal.)
Within the confines of the question, I'd use std::weak_ptr<void> instead of void*, as std::weak_ptr<T> can tell when there are no more "strong references" to the object around, but won't prevent the object from being deleted by maintaining a reference.
std::map<std::weak_ptr<void>, MyUserData> myMap;
template <typename T>
registerObject<T>(const std::shared_ptr<T> & _object)
{
static inc = 0;
Internal_RemoveDeadObjects();
myMap[std::weak_ptr<void>(_object)].someNum = inc++;
}
template <typename T>
MyUserData getRegisteredData(const std::shared_ptr<T> & _object)
{
Internal_RemoveDeadObjects();
return myMap[std::weak_ptr<void>(_object)];
}
void Internal_RemoveDeadObjects()
{
auto iter = myMap.cbegin();
while (iter != myMap.cend())
{
auto& weakPtr = (*iter).first;
const bool needsRemoval = !(weakPtr.expired());
if (needsRemoval)
{
auto itemToRemove = iter;
++iter;
myMap.erase(itemToRemove);
}
else
{
++iter;
}
}
}
Basically, std::weak_ptr and std::shared_ptr collaborate and std::weak_ptr can detect when there are no more std::shared_ptr references to the object in question. Once that is the case, we can remove the ancillary data from myMap. I'm using the two interfaces to myMap, your registerObject and my getRegisteredData as convenient places to call Internal_RemoveDeadObjects to perform the clean up.
Yes, this walks the entirety of myMap every time a new object is registered or the registered data is requested. Modify as you see fit or try a different design.
You ask "Should I even worry about leaving the user data in the map? What are the chances that an object is allocated with the same address as a previously deleted object?" In my experience, decidedly non-zero, so don't do this. :-)
I'd add a deregister method, and make the user deregister their objects. With the interface as given, where you're stripping the type away, I can't see a way to check for the ref-count, and C++ doesn't provide a way to check whether memory has been deleted or not.
I thought about it for a while and this is as far as I got:
#include <memory>
#include <map>
#include <iostream>
#include <cassert>
using namespace std;
struct MyUserData
{
int someNum;
};
map<void *, MyUserData> myMap;
template<class T>
class my_shared_ptr : public shared_ptr<T>
{
public:
my_shared_ptr() { }
my_shared_ptr(const shared_ptr<T>& s) : shared_ptr<T>(s) { }
my_shared_ptr(T* t) : shared_ptr<T>(t) { }
~my_shared_ptr()
{
if (unique())
{
myMap.erase(get());
}
}
};
template <typename T>
void registerObject(const my_shared_ptr<T> & _object)
{
static int inc = 0;
myMap[(void *)_object.get()].someNum = inc++;
}
struct MyObject
{
int asdf;
};
int main()
{
{
my_shared_ptr<MyObject> obj2;
{
my_shared_ptr<MyObject> obj = make_shared<MyObject>();
obj->asdf = 5;
registerObject(obj);
obj2 = obj;
assert(myMap.size() == 1);
}
/* obj is destroyed, but obj2 still points to the data */
assert(myMap.size() == 1);
}
/* obj2 is destroyed, nobody points to the data */
assert(myMap.size() == 0);
}
Note however that it wouldn't work if you wrote obj = nullptr; , or obj.reset(), since the object isn't destroyed in those cases (no destructor called). Also, you can't use auto with this solution.
Also, be careful not to call (void *)&_object.get() like you were doing. If I'm not terribly wrong, by that statement you're actually taking the address of the temporary that _object.get() returns, and casting it to void. That address, however, becomes invalid instantly after.
This sounds like a job for... boost::intrusive (http://www.boost.org/doc/libs/1_53_0/doc/html/intrusive.html)! I don't think the current interface will work exactly as it stands though. I'll try to work out a few more details a little later as I get a chance.
You can just do
map.erase(map.find(obj));
delete obj;
obj = 0;
this will call the destructor for your user data and remove it from the map.
Or you could make your own manager:
class Pointer;
extern std::map<Pointer,UserData> data;
class Pointer
{
private:
void * pointer;
public:
//operator ()
void * operator()()
{
return pointer;
}
//operator =
Pointer& operator= (void * ptr)
{
if(ptr == 0)
{
data.erase(data.find(pointer));
pointer = 0;
}
else
pointer = ptr;
return *this;
}
Pointer(void * ptr)
{
pointer = ptr;
}
Pointer()
{
pointer = 0;
}
~Pointer(){}
};
struct UserData
{
static int whatever;
UserData(){}
};
std::map<Pointer,UserData> data;
int main()
{
data[Pointer(new UserData())].whatever++;
data[Pointer(new UserData())].whatever++;
data[Pointer(new UserData())].whatever++;
data[Pointer(new UserData())].whatever++;
Pointer x(new UserData());
data[x].whatever;
x = 0;
return 0;
}
Here's my problem,
Class MClass {
public:
void Add(OtherClass* objects) {
_objects = objects;
}
private:
OtherClass* _objects;
}
//otherfile.cpp
void Setup() {
MClass myObj;
OtherClass obj[NUMBER_OF_OBJECTS];
//obj initialization here
//...
myObj.Add(obj);
}
It will cause a RT error because the *obj diminishes after the end of the function body.
But, how can make this one valid?
I like to initialized first an object before assigning it to other class.
EDIT
I don't want to use storage classes or something here, I just want a raw array since it is very expensive for me to use. Its functionality will not lessen my problem here.
So how do I do that in a raw-array style?
Class MClass {
public:
void Add(std::vector<OtherClass> objects) {
_objects = std::move(objects);
}
private:
std::vector<OtherClass> _objects;
}
//otherfile.cpp
void Setup() {
MClass myObj;
std::vector<OtherClass> obj(NUMBER_OF_OBJECTS);
myObj.Add(std::move(obj));
}
In your example, you store a pointer to a local array. If the method ends, the array goes out of scope and doesn't exist anymore.
This is the reason, your pointer is not valid anymore. If you want to solve this, learn about the scope of variables in C++.
It is not completely clear what you are trying to do, but you could store a collection of objects instead of a pointer:
class MClass
{
public:
void Add(const std::vector<OtherClass>& objects) {
objects_ = objects;
}
void Add(std::vector<OtherClass>&& objects) {
objects_ = std::move(objects);
}
private:
std::vector<OtherClass> objects_;
};
then
void Setup()
{
MClass myObj;
std::vector<OtherClass> obj(NUMBER_OF_OBJECTS);
//obj initialization here
//...
myObj.Add(std::move(obj)); // move obj's contents onto myObs's objects.
}
Stop using raw arrays, and use either std::vector or std::array. Then you don't have to worry about it anymore.
If you really want to do it manually, you have to copy is manually as well. Using e.g. std::vector and std::move is more effective, but here you go:
Class MClass {
public:
MClass()
: _objects(nullptr), _count(0)
{}
MClass(const MClass& other)
: _objects(nullptr), _count(0)
{
Add(other._objects, other._count);
}
~MClass()
{
if (_objects != nullptr)
delete [] _objects;
}
void Add(const OtherClass* objects, const size_t count)
{
if (_objects != nullptr)
delete [] _objects;
_objects = new [count];
for (size_t i = 0; i < count; i++)
_objects[i] = objects[i];
_count = count;
}
MClass& operator=(const MClass& other)
{
Add(other._objects, other._count);
}
private:
OtherClass* _objects;
size_t _count;
};
// ...
myObj.Add(obj, NUMBER_OF_OBJECTS);
As you can see, it's a lot of more code, which makes it harder to follow and debug, and also larger possibility of errors. And not as "effective" as I said above.
I need to pass a pointer to a class so some code I don't control. This code automatically free()s the pointer when it is done, but I need the class later. I hoped I could just make a 'wrapper' class that would keep the class from being deallocated without actually preventing the code from accessing it, but virtual calls don't work.
template <class T>
class PointerWrapper:public T
{
public:
T* p;
PointerWrapper(T *ptr)
{
p=ptr;
}
~PointerWrapper(void)
{
}
T* operator->() const
{
return p;
}
T& operator*() const
{
return *p;
}
};
void codeIDontControl(Example *ex)
{
ex->virtualfunction();
delete ex;
}
void myCode()
{
Example *ex=new Example();
codeIDontControl(ex);
do something with ex //doesn't work because ex has been freed
codeIDontControl(new PointerWrapper<Example>(ex));
do something with ex //ex hasn't been freed, but the changes made to it via
// Example::virtualfunction() in codeIDontControl() aren't there anymore
}
Basically, ex->virtualfunction() calls the virtual function in PointerWrapper itself instead of the virtual function in PointerWrapper->p. It seems that it's ignoring the -> operator?
Now, I don't need to use a PointerWrapper-esque class if there's a different way to do this, but it was all I could think of...
I can't modify Example either, but I can subclass it
You should provide Forwarder class - which redirects virtual calls to stored pointer. Freeing of forwarder class will not cause releasing of pointee. This approach does NOT need to do copy (which can be expensive/may be not implemented/or even not make sense):
struct Forwarder : Example
{
Example *impl;
Forwarder(Example *i) : impl(i) {}
void virtualfunction()
{
impl->virtualfunction();
}
};
Full code:
live demo:
#include <iostream>
#include <ostream>
using namespace std;
struct Example
{
virtual void virtualfunction()=0;
virtual ~Example() {}
};
struct Implmenetation : Example
{
bool alive;
Implmenetation() : alive(true) {}
void virtualfunction()
{
cout << "Implmenetation::virtualfunction alive=" << alive << endl;
}
~Implmenetation()
{
alive=false;
cout << "Implmenetation::~Implmenetation" << endl;
}
};
struct Forwarder : Example
{
Example *impl;
Forwarder(Example *i) : impl(i) {}
void virtualfunction()
{
impl->virtualfunction();
}
};
void codeIDontControl(Example *ex)
{
ex->virtualfunction();
delete ex;
}
void myCode()
{
Implmenetation impl;
codeIDontControl(new Forwarder(&impl));
//do something with ex //doesn't work because ex has been freed
impl.virtualfunction();
}
int main()
{
myCode();
}
Output is:
Implmenetation::virtualfunction alive=1
Implmenetation::virtualfunction alive=1
Implmenetation::~Implmenetation
It's bad design, really. Only the allocator should be allowed to free memory. Functions like this are dangerous, as they leave with with dangling pointers.
This is just off the top of my head, maybe you could try something like this? It's not a safe idea, but if someone implemented it I would be interested to know what happens.
class Foo
{
Foo(Foo* copy) : m_copy(copy) {}
~Foo() { if(m_copy) { *m_copy = *this; } } // Use copy constructor to create copy on destuction.
Foo* m_copy;
}
Foo copy(NULL);
Foo* original = new Foo(©);
MethodThatDeletes(original);
// Original should be destroyed, and made a copy in the process.
original = NULL;
// Copy should be a copy of the original at it's last know state.
copy;
You are providing a Example* to codeIDontControl. The overloaded operator-> on PointerWrapper is an for the PointerWrapper type not the Example* type or even the PointerWrapper* type (i.e. for a value or reference of that type not a pointer to that type).
Since the function you need to call isn't controlled by you, you will need to provide a complete wrapper of the type it expects as a wrapper over the instance you wish to control the lifetime of.