I have some legacy-era code at work that takes in a double-pointer and allocates memory to it. A shortened example of it would look something like this:
struct LegacyObj
{
int a;
double b;
};
void LegacyAllocator(LegacyObj** ppObj)
{
*ppObj = (LegacyObj*)malloc(sizeof(LegacyObj));
}
void LegacyDeleter(LegacyObj** ppObj)
{
free(*ppObj);
}
The actual LegacyAllocator function is ~100 lines and mixes reading from files with creating a linked list of LegacyObj pointers, and isn't something I'd be able to get away with rewriting right now. I would like, however, to make the use of this function a bit safer, avoiding any memory leaks that may occur from exceptions &tc. The first solution I came up with was to wrap it up in a class and handle calling the legacy functions in the ctor/dtor.
class RAIIWrapper
{
public:
RAIIWrapper()
:obj{nullptr}
{
::LegacyAllocator(&obj);
}
RAIIWrapper(RAIIWrapper&& that)
: obj{ that.obj}
{
that.obj = nullptr;
}
RAIIWrapper& operator=(RAIIWrapper&& that)
{
RAIIWrapper copy{std::move(that)};
std::swap(obj, copy.obj);
return *this;
}
~RAIIWrapper ()
{
::LegacyDeleter(&obj);
}
private:
LegacyObj* obj;
};
But I'm curious - is there a way to do this using std::shared_ptr or std::unique_ptr? I've not been able to come up with a solution without having to keep the original pointer passed to LegacyAllocator around.
Yes, you can use a custom deleter with std::unique_ptr or std::shared_ptr, for example:
struct Deleter {
void operator()(LegacyObj *p) const {
LegacyDeleter(&p);
}
};
std::unique_ptr<LegacyObj, Deleter> MakeLegacyObj() {
LegacyObj *p = 0;
LegacyAllocator(&p);
return std::unique_ptr<LegacyObj, Deleter>(p);
}
std::unique_ptr<LegacyObj, Deleter> p = MakeLegacyObj();
And, as correctly pointed out by #Dave, this works with shared_ptr too:
std::shared_ptr<LegacyObj> p = MakeLegacyObj();
You can use unique_ptr to delete the memory, but you'll have to provide a custom Deleter class since the memory is allocated using malloc rather than new.
Better yet, change the allocation code to use new instead and just use unique_ptr. If you go down this road you can just have the allocator return a unique_ptr instead of a pointer to the memory.
Assuming you need to provide your own custom deleter, here is one way you might do it:
template <typename T>
class MallocDeleter
{
public:
void operator() (T* obj) const
{
LegacyDeleter (*obj);
}
};
typedef std::unique_ptr <LegacyObj, MallocDeleter <LegacyObj>> unique_legacy_ptr;
You could also probably provide a make_unique_legacy type function which allocates by calling LegacyAllocator, instead of having to initialize the unique_ptr yourself.
You can create a factory function for unique_ptrs like this:
typedef void(* LegacyDeleterType)(LegacyObj*);
typedef std::unique_ptr<LegacyObj,LegacyDeleterType> UniqueLegacyPtr;
UniqueLegacyPtr makeUniqueLegacyObj()
{
LegacyObj * p = nullptr;
LegacyAllocator( &p );
return UniqueLegacyPtr( p, [](LegacyObj*p){ LegacyDeleter(&p); } );
}
You can now use that to create unique_ptrs and you can also assign to shared_ptrs which capture the custom deleter automatically at construction:
int main()
{
auto unique = makeUniqueLegacyObj();
std::shared_ptr<LegacyObj> shared = makeUniqueLegacyObj();
}
Related
In C++ code that I wrote to demonstrate an algorithm in an answer, I'm creating structs in a function using new, storing them in a list, moving them to a vector, then returning the vector:
struct my_struct {int a, b, c;};
std::vector<my_struct> myFunction(...) {
std::list<my_struct> my_list;
std::list<my_struct>::iterator current = my_list.begin();
std::vector<my_struct> my_vector;
my_struct *new_struct = nullptr;
while (...) {
...
if (!new_struct) {
new_struct = new my_struct;
new_struct->a = ...
}
...
if (new_struct) {
new_struct->b = ...
my_list.insert(current, *my_struct);
my_struct = nullptr;
}
...
if (...) {
current->c = ...
my_vector.push_back(*current);
current = my_list.erase(current);
}
...
}
return my_vector;
}
It compiles and seems to work correctly, however I'm more used to JavaScript and this code just feels like translated JavaScript; I'm specifically wondering whether I'm creating memory leaks, and whether I have to delete the structs in the calling function (and how).
Yes, you have a memory leak. If you invoke the new command, you will need to invoke a delete command in the future to free the memory allocated by new.
So, in this statement:
my_list.insert(current, *my_struct);
you are indeed copy the contents of *my_struct, not getting the ownership of it. So, in the following statement:
my_struct = nullptr;
You just got a memory leak.
To solve this, change your design to use smartpointer, for example, unique_ptr, or, better yet, dont use pointer at all, and just use a plain object:
my_struct new_struct;
As others in the question section have already pointed out, you probably shouldn't use new at all. The only reason to use pointers there at all is the if(newstruct) checks, if they are an essential part of your algorithm.
But if you use new, you should delete, too. It's safe to do that after inserting the struct into the list or vector - the list and vector contain copies.
Beginning with C++17, std::optional (and before that, boost::optional) is a sensible alternative solution for your specific problem here. It removes the need for pointers and the danger of memory leaks but at the same time still gives you a "nothing" state.
Your pseudo code would become something like:
// this is the correct way of defining a struct in C++:
struct my_struct {
int a;
int b;
int c;
};
std::vector<my_struct> myFunction(...) {
std::list<my_struct> my_list;
std::list<my_struct>::iterator current = my_list.begin();
std::vector<my_struct> my_vector;
std::optional<my_struct> new_struct; // new_struct does not hold a value
while (...) {
...
if (!new_struct.has_value()) { // if it does not hold a value...
new_struct = my_struct(); // it holds a value now (a default my_struct)
new_struct->a = ... // access syntax like a pointer
}
...
if (new_struct.has_value()) {
new_struct->b = ...
my_list.insert(current, *new_struct); // dereference syntax like a pointer
new_struct.reset(); // it no longer holds a value now
}
...
if (...) {
current->c = ...
my_vector.push_back(*current);
current = my_list.erase(current);
}
...
}
return my_vector;
}
Note how the syntax of std::optional deliberately mimics that of pointers.
I have a class that contains several arrays whose sizes can be determined by parameters to its constructor. My problem is that instances of this class have sizes that can't be determined at compile time, and I don't know how to tell a new method at run time how big I need my object to be. Each object will be of a fixed size, but different instances may be different sizes.
There are several ways around the problem:- use a factory- use a placement constructor- allocate arrays in the constructor and store pointers to them in my object.
I am adapting some legacy code from an old application written in C. In the original code, the program figures out how much memory will be needed for the entire object, calls malloc() for that amount, and proceeds to initialize the various fields.
For the C++ version, I'd like to be able to make a (fairly) normal constructor for my object. It will be a descendant of a parent class, and some of the code will be depending on polymorphism to call the right method. Other classes descended from the same parent have sizes known at compile time, and thus present no problem.
I'd like to avoid some of the special considerations necessary when using placement new, and I'd like to be able to delete the objects in a normal way.
I'd like to avoid carrying pointers within the body of my object, partially to avoid ownership problems associated with copying the object, and partially because I would like to re-use as much of the existing C code as possible. If ownership were the only issue, I could probably just use shared pointers and not worry.
Here's a very trimmed-down version of the C code that creates the objects:
typedef struct
{
int controls;
int coords;
} myobject;
myobject* create_obj(int controls, int coords)
{
size_t size = sizeof(myobject) + (controls + coords*2) * sizeof(double);
char* mem = malloc(size);
myobject* p = (myobject *) mem;
p->controls = controls;
p->coords = coords;
return p;
}
The arrays within the object maintain a fixed size of the life of the object. In the code above, memory following the structure of myobject will be used to hold the array elements.
I feel like I may be missing something obvious. Is there some way that I don't know about to write a (fairly) normal constructor in C++ but be able to tell it how much memory the object will require at run time, without resorting to a "placement new" scenario?
How about a pragmatic approach: keep the structure as is (if compatibility with C is important) and wrap it into a c++ class?
typedef struct
{
int controls;
int coords;
} myobject;
myobject* create_obj(int controls, int coords);
void dispose_obj(myobject* obj);
class MyObject
{
public:
MyObject(int controls, int coords) {_data = create_obj(controls, coords);}
~MyObject() {dispose_obj(_data);}
const myobject* data() const
{
return _data;
}
myobject* data()
{
return _data;
}
int controls() const {return _data->controls;}
int coords() const {return _data->coords;}
double* array() { return (double*)(_data+1); }
private:
myobject* _data;
}
While I understand the desire to limit the changes to the existing C code, it would be better to do it correctly now rather than fight with bugs in the future. I suggest the following structure and changes to your code to deal with it (which I suspect would mostly be pulling out code that calculates offsets).
struct spots
{
double x;
double y;
};
struct myobject
{
std::vector<double> m_controls;
std::vector<spots> m_coordinates;
myobject( int controls, int coordinates ) :
m_controls( controls ),
m_coordinates( coordinates )
{ }
};
To maintain the semantics of the original code, where the struct and array are in a single contigious block of memory, you can simply replace malloc(size) with new char[size] instead:
myobject* create_obj(int controls, int coords)
{
size_t size = sizeof(myobject) + (controls + coords*2) * sizeof(double);
char* mem = new char[size];
myobject* p = new(mem) myobject;
p->controls = controls;
p->coords = coords;
return p;
}
You will have to use a type-cast when freeing the memory with delete[], though:
myobject *p = create_obj(...);
...
p->~myobject();
delete[] (char*) p;
In this case, I would suggest wrapping that logic in another function:
void free_obj(myobject *p)
{
p->~myobject();
delete[] (char*) p;
}
myobject *p = create_obj(...);
...
free_obj(p);
That being said, if you are allowed to, it would be better to re-write the code to follow C++ semantics instead, eg:
struct myobject
{
int controls;
int coords;
std::vector<double> values;
myobject(int acontrols, int acoords) :
controls(acontrols),
coords(acoords),
values(acontrols + acoords*2)
{
}
};
And then you can do this:
std::unique_ptr<myobject> p = std::make_unique<myobject>(...); // C++14
...
std::unique_ptr<myobject> p(new myobject(...)); // C++11
...
std::auto_ptr<myobject> p(new myobject(...)); // pre C++11
...
New Answer (given comment from OP):
Allocate a std::vector<byte> of the correct size. The array allocated to back the vector will be contiguous memory. This vector size can be calculated and the vector will manage your memory correctly. You will still need to be very careful about how you manage your access to that byte array obviously, but you can use iterators and the like at least (if you want).
By the way here is a little template thing I use to move along byte blobs with a little more grace (note this has aliasing issues as pointed out by Sergey in the comments below, I'm leaving it here because it seems to be a good example of what not to do... :-) ) :
template<typename T>
T readFromBuf(byte*& ptr) {
T * const p = reinterpret_cast<T*>(ptr);
ptr += sizeof(T);
return *p;
}
Old Answer:
As the comments suggest, you can easily use a std::vector to do what you want. Also I would like to make another suggestion.
size_t size = sizeof(myobject) + (controls + coords*2) * sizeof(double);
The above line of code suggests to me that you have some "hidden structure" in your code. Your myobject struct has two int values from which you are calculating the size of what you actually need. What you actually need is this:
struct ControlCoord {
double control;
std::pair<double, double> coordinate;
};
std::vector<ControlCoord>> controlCoords;
When the comments finally scheded some light on the actual requirements, the solution would be following:
allocate a buffer large enough to hold your object and the array
use placement new in the beginning of the buffer
Here is how:
class myobject {
myobject(int controls, int coords) : controls(controls), coords(coords) {}
~myobject() {};
public:
const int controls;
const int coords;
static myobject* create(int controls, int coords) {
std::unique_ptr<char> buffer = new char[sizeof(myobject) + (controls + coords*2) * sizeof(double)];
myobject obj* = new (buffer.get()) myobject(controls, coords);
buffer.release();
return obj;
}
void dispose() {
~myobject();
char* p = (char*)this;
delete[] p;
}
};
myobject *p = myobject::create(...);
...
p->dispose();
(or suitably wrapped inside deleter for smart pointer)
I want to use smart pointer in the following situation:
SOME_STRUCT* ptr = new SOME_STRUCT;
ptr->SOME_MEMBER = new BYTE[100];
CallSomeAPI(ptr);
now the API can either return error or pass successfully but in both those cases i want to delete the object , one way can be to write delete statement during error exit and during normal exit.
But how can i use a smart pointer for these pointers ?
By smart pointers i mean unique_ptr, shared_ptr , etc. whichever can work !
Thanks!
You can write a custom deleter for unique_ptr.
struct my_deleter {
void operator()(SOME_STURCT* ptr) const {
delete[] ptr->SOME_MEMBER;
delete ptr;
}
};
using my_ptr = std::unique_ptr<SOME_STRUCT, my_deleter>;
and I would suggest changing new SOME_STRUCT; to new SOME_STRUCT{}; to default initialize SOME_MEMBER to nullptr.
I am not 100% happy with this solution, so perhaps look into scope_guard or writing a wrapper class for your struct.
I assume you cannot modify SMOE_STRUCT to add a destructor to it. This leaves you with two options: a custom deleter, and encapsulation.
First, you could create a custom deleter for use with std::unique_ptr:
struct SOME_STRUCT_Deleter
{
void operator() (SOME_STRUCT *p) const
{
delete[] p->SOME_MEMBER;
delete p;
}
};
std::unique_ptr<SOME_STRUCT, SOME_STRUCT_Deleter> ptr{new SOME_STRUCT};
ptr->SOME_MEMBER = new BYTE[100];
CallSomeAPI(ptr.get());
If you find that, unlike the situation described in your question, shared ownership would suit you better than exclusive one, you can use the deleter with a shared_ptr as well, like this:
std::shared_ptr<SOME_STRUCT> ptr{new SOME_STRUCT, SOME_STRUCT_Deleter{}};
ptr->SOME_MEMBER = new BYTE[100];
CallSomeAPI(ptr.get());
A second option, which I find preferable, is to wrap SOME_STRUCT:
struct SOME_STRUCT_plus_plus
{
SOME_STRUCT s;
~SOME_STRUCT_plus_plus()
{
delete[] s.SOME_MEMBER;
}
SOME_STRUCT_plus_plus()
{
s.SOME_MEMBER = new BYTE[100];
}
};
std::unique_ptr<SOME_STRUCT_plus_plus> ptr{new SOME_STRUCT_plus_plus};
CallSomeAPI(&ptr->s);
You could even "wrap" it by making SOME_STRUCT_plus_plus derive from SOME_STRUCT instead of aggregating it, which would give you direct access to members without the need to go through s. At the same time, it could lead to memory leaks if someone cast SOME_STRUCT_plus_plus* to SOME_STRUCT* and then called delete on it.
Here, it seems that all can be on the stack:
SOME_STRUCT ptr; // or auto ptr = std::make_unique<SOME_STRUCT>();
BYTE bytes[100]; // or std::vector<BYTE> bytes(100);
ptr.SOME_MEMBER = bytes; // or ptr->SOME_MEMBER = bytes.data();
CallSomeAPI(&ptr); // or CallSomeAPI(ptr.get());
I know that whenever I create a new object for a class, that object is stored in memory. I also know that in creating that object, it can only be accessed within the set of braces it is created in (Scope visibility). I need to find a way to delete that object outside of the braces it is created in. I have looked at smart pointers briefly, and it might be what I want to use? I'm assuming it is, I just don't know for sure. If a smart pointer can satisfy my needs, would someone please provide me with an example of how to use a smart pointer to access an object outside of where it has been created? Thanks :)
EDIT:
Example of what I'm trying to do:
class ModernWarfare2
{
//my class
ModernWarfare2();
};
DWORD XamHook(DWORD r3, DWORD r4, DWORD r5)
{
switch(XamGetCurrentTitleId())//a function that tells what game is being played
{
case Xbox360Dashboard://if i were to exit the game mw2
{
if(CODAllocated)//a boolean
{
//free the memory of the previous cod game
if(MW2Allocated)//another boolean
{
delete[] MW2;//gives me an error because i dont have access to MW2
}
}
break;
}
case COD_MW2:
{
if(!CODAllocated)
{
if(!MW2Allocated)
{
ModernWarfare2 *MW2 = new ModernWarfare2();
}
}
break;
}
}
return XamInputGetState(r3,r4,r5);
}
How do I fix my issue?
I also know that in creating that object, the object can only be accessed within the set of braces it is created in.
Not necessarily; that's only true when you construct objects with automatic storage duration, like this:
void foo()
{
T obj;
}
Such objects, yes, go out of scope.
Objects you allocate dynamically do not:
void foo()
{
T* obj = new T();
}
This is a memory leak because you never destroy *obj; however, you can access it from pretty much wherever you like:
T* foo()
{
return new T();
}
void bar()
{
T* obj = foo();
// yay!
}
or:
T* obj = nullptr;
void foo()
{
obj = new T();
}
void bar()
{
// do stuff with *obj
}
void baz()
{
foo();
bar();
}
This all gets dangerous and messy because you end up with spaghetti code in which the lifetime of the dynamically-allocated object is unclear, and in the examples above I still haven't approached the topic of eventually destroying the object. You have to be really careful not to destroy it whilst you're still using it.
This is where smart pointers come in, but if you want a tutorial on using smart pointers I'm going to have to refer you back to your C++11 book.
"I also know that in creating that object, the object can only be accessed within the set of braces it is created in." - This depends on how you create the object.
Example 1 (can't be accessed outside braces):
void func(void)
{
Object obj("foo", "bar");
}
Example 2 (can be accessed outside braces):
Object* func(void)
{
Object* obj = new Object("foo", "bar");
return obj;
}
Example 2 can be deleted using the keyword delete.
Take a look here for more information on pointers.
I haven't personally found a use for smart pointers but MSDN has good information on the topic here
By creating MW2 with
{
ModernWarfare2 *MW2 = new ModernWarfare2();
}
I was not able to reference MW2 elsewhere. By doing this, I can create it and delete it in two different spots:
class ModernWarfare2
{
//my class
ModernWarfare2();
};
ModernWarfare2 *MW2 = NULL;
DWORD XamHook(DWORD r3, DWORD r4, DWORD r5)
{
switch(XamGetCurrentTitleId())//a function that tells what game is being played
{
case Xbox360Dashboard://if i were to exit the game mw2
{
if(CODAllocated)//a boolean
{
//free the memory of the previous cod game
if(MW2Allocated)//another boolean
{
delete MW2;//gives me an error because i dont have access to MW2
}
}
break;
}
case COD_MW2:
{
if(!CODAllocated)
{
if(!MW2Allocated)
{
if(MW2 == NULL)
{
MW2 = new ModernWarfare2();
}
}
}
break;
}
}
return XamInputGetState(r3,r4,r5);
}
I think what you need is basic design pattern
Make the data and the functions members of a class
class SomeHandler
{
public:
void Acquire( /* some source */ );
void DoSomething( /* eventual parameters */ );
bool TrySomething(); // returns true if successful
private:
void internalFunction();
bool inGoodState;
SomeType dataINeed;
SomeOtherType otherData;
};
void SomeHandler::Acquire( /**/ )
{
// implement like this
}
now the functions can access the all the data
the use it like
int main()
{
SomeHandler h;
h.Acquire();
if( h.TrySomething() )
{
h.DoSomething();
}
}
Based on your code snippet, You have to save your pointer MW2 for
future so that you can delete the pointer.
I would suggest you to change
if(!MW2Allocated)
to
if(!MW2)
so that you don't have to create another variable for saving the reference to your allocated memory
Offcourse you have to move
ModernWarfare2 *MW2
to a larger scope (move it to the scope same as MW2Allocated) and initialize it to NULL.
Use "nullptr" instead of "NULL" if you are using C++11 supported compiler.
Also makesure you use
delete
instead of
delete[]
since this is not an array allocation
I don't think you can use smart pointers to skip saving your reference to the allocated memory,
since they are meant to make the memory deletion automatic or to make sure two deletion doesn't occur
for the same memory.
Refer to
http://www.codeproject.com/Articles/541067/Cplusplus-Smart-Pointers
for a good explanation about smart pointers
Say I have a pointer like this:
int *thingy;
At some point, this code may or may not be called:
thingy=new int;
How do I know if I can do this:
delete thingy;
I could use a bool for every pointer and mark the bool as true whenever the I use new, but I have many pointers and that would get very unwieldy.
If I have not called new on thingy, calling delete on it would likely cause a crash, right?
I searched around quite a bit but could find no answer that clearly fit my situation.
EDIT: I need to be able to delete the pointers as many times as I like without the pointers necessarily pointing to any data. If this is impossible I'll have to re-write my code.
Initialize it to NULL always
int *thingy = NULL;
and then
delete thingy;
thingy = NULL;
is valid even if thingy is NULL. You can do the delete as many times as you want as long as thingy is NULL delete will have no unwanted side effects.
There's no built-in way to tell if a particular pointer value is deleteable. Instead you simply have to design the program to do the right thing, preferably by carefully designing resource ownership policies in line with your requirements and them implementing them with something like RAII.
Given appropriate RAII types you will not need to scatter deletes or other resource management commands around your code. You will simply initialize and use objects of the appropriate types, and leave clean up to the objects themselves. For example if the RAII type unique_ptr corresponds to an ownership policy you want to use then you can manage an object this way:
unique_ptr<int> thingy {new int};
// use thingy ...
There's no need to manually cleanup, because unique_ptr takes care of that for you.
On the other hand if you try to manage resources directly you end up with lots of code like:
int *thingy = nullptr;
// ...
thingy = new int;
try {
// something that might throw
} catch(...) {
delete thingy;
thingy = nullptr;
throw;
}
delete thingy;
thingy = nullptr;
There is no builtin C++ tool to identify if a pointer points to heap data and can safely deleted. It's safe to delete a NULL pointer and you can set every pointer whose data has been deleted to NULL. But this doesn't help to differentiate between pointers to heap data and pointers to other data or to code.
When your operation system starts a process it will locate the code and data sections to specific data areas. In Windows this is partially controlled by the PE header of the EXE file. Therefore the actual address of the memory regions may vary. But you can identify where theses regions are located:
code
bss
data
stack
heap
After obtaining the address range for each region you can differentiate between a pointer to the heap data (where delete is appropriate) and a pointer to stack data. This allows you to differetiate between deleteable and data whose pointer you must not delete.
Write a wrapper class that does the tracking for you, eg:
template<typename T>
class ptr_t
{
private:
T* m_ptr;
bool m_delete;
ptr_t(const ptr_t&) {}
ptr_t& operator=(const ptr_t&) { return *this; }
public:
ptr_t()
: m_ptr(NULL), m_delete(false)
{
}
ptr_t(T *ptr, bool del)
: m_ptr(ptr), m_delete(del)
{
}
~ptr_t()
{
reset();
}
void assign(T *ptr, bool del)
{
if (m_delete)
delete m_ptr;
m_ptr = ptr;
m_delete = del;
}
void reset()
{
assign(NULL, false);
}
operator T*() { return m_ptr; }
bool operator!() const { return (!m_ptr); }
};
typedef ptr_t<int> int_ptr;
.
int_ptr thingy;
...
thingy.assign(new int, true);
...
thingy.reset();
.
int i;
int_ptr pi;
...
pi.assign(&i, false);
...
pi.reset();