atomicgs12
asked on
How to handle pointers to pointers C++
I was wondering what is the correct to handle pointers to pointers, that is passing them into a function and delete them on return if the function receiving the pointers creates the memory but does not release it.
Say I have some code as below:
char *pInBuff;
ReturnData(char** pData);
Where ReturnData is defined something like:
ReturnData(&pInBuff)
{
*pInbuff = new char[128];
// load pInBuff with data
}
What is proper way to free pInBuff? Is it a simple delete pInbuff, delete [] pInBuff or something else?
Thanks
Say I have some code as below:
char *pInBuff;
ReturnData(char** pData);
Where ReturnData is defined something like:
ReturnData(&pInBuff)
{
*pInbuff = new char[128];
// load pInBuff with data
}
What is proper way to free pInBuff? Is it a simple delete pInbuff, delete [] pInBuff or something else?
Thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
To make it a little clearer, wrap the whole thing in a class and then pass an instance of the class around
// file MyBuffer.h
class MyBuffer
{
private:
char* m_buffer = NULL;
protected:
void Empty();
public:
MyBuffer();
~MyBuffer();
void CleanData();
}
// file MyBuffer.cpp
MyBuffer::~MyBuffer
{
Empty();
}
MyBuffer::Empty()
{
if ( m_buffer != NULL )
{
delete [] m_buffer;
m_buffer = NULL;
}
}
MyBuffer::CleanData()
{
Empty();
}
bool MyBuffer::IsEmpty()
{
return ( m_buffer == NULL )
}
bool MyBuffer::LoadData( const char* data )
{
bool retStatus = false;
if ( IsEmpty() )
{
if ( data != NULL ) && ( strlen( data ) > 0 )
{
m_buffer = new char[strlen( data ) + 1];
retStatus = true;
}
}
return retStatus;
}
// in file using this class
// on stack
{
MyBuffer buff;
char* TestData = "This is test data";
buff.LoadData( TestData);
}
// or on heap
{
MyBuffer buff = new MyBuffer();
char* TestData = "This is test data";
buff->LoadData( TestData);
delete buff;
}
opps a little too quick
last bit should read
last bit should read
// in file using this class
// on stack
{
bool AllOK = true;
MyBuffer buff;
char* TestData = "This is test data";
ALLOK = buff.LoadData( TestData);
if ( ALLOK )
{
// success
}
else
{
// error
}
}
// or on heap
{
bool AllOK = true;
MyBuffer buff = new MyBuffer();
char* TestData = "This is test data";
AllOK = buff->LoadData( TestData);
if ( ALLOK )
{
// success
}
else
{
// error
}
delete buff;
}
why not simply use std::vector?
you don't need care for allocation or deallocation yourself. and the called function freely can increase the buffer as needed. and if you need a char* pointer you get it by &v[0] (only if v.size() > 0).
Sara
std::vector<char> v;
getdata(v);
...
void getdata(std::vector<char> & v)
{
v.resize(128, ' '); // 128 space characters
}
you don't need care for allocation or deallocation yourself. and the called function freely can increase the buffer as needed. and if you need a char* pointer you get it by &v[0] (only if v.size() > 0).
Sara
Wow - just noticed a typo in my previous post :
>> (a) make use of SQL data structures like std::string
STL of course, not SQL hehe.
>> (a) make use of SQL data structures like std::string
STL of course, not SQL hehe.
Hmm, perhaps I read the question too literally. ;)
ASKER
tgerbert - Are you second quessing yourself? I appreciate all the cool solutions from everyone but I was just looking for something simple and straight forward.
delete [] pInBuff; should be fine, yes?
delete [] pInBuff; should be fine, yes?
Then in that case, yup, delete [] pInBuff. Though I do like Infinity's comment.
ASKER
as per Infinity's solution:
a. I need this to be Unicode so std:string is out
b. The user may what to keep the data around even after the object that allocated it is destroyed
Thanks to all
a. I need this to be Unicode so std:string is out
b. The user may what to keep the data around even after the object that allocated it is destroyed
Thanks to all
a: std::wstring
b: the caller can control the lifetime of the data by controlling the scope of the object
b: the caller can control the lifetime of the data by controlling the scope of the object
>> a. I need this to be Unicode so std:string is out
Your current approach of using a char* would be out too ;)
This remark also doesn't invalidate the point I was trying to make ... which was that you have several options that are better than your current approach. One of them is to use an existing solution (whether that be std::string or something else).
>> b. The user may what to keep the data around even after the object that allocated it is destroyed
As tgerbert said : if you want to keep the object, then keep it - nothing is forcing you to clean up the object at any other time than the time that you choose.
The point of encapsulating the buffer in a class, is to make your life easier, by hiding the memory allocation details from the calling code.
Your current approach of using a char* would be out too ;)
This remark also doesn't invalidate the point I was trying to make ... which was that you have several options that are better than your current approach. One of them is to use an existing solution (whether that be std::string or something else).
>> b. The user may what to keep the data around even after the object that allocated it is destroyed
As tgerbert said : if you want to keep the object, then keep it - nothing is forcing you to clean up the object at any other time than the time that you choose.
The point of encapsulating the buffer in a class, is to make your life easier, by hiding the memory allocation details from the calling code.
Something like below.
Or better yet : since you're using C++, you could :
(a) make use of SQL data structures like std::string
(b) encapsulate the buffer in a class that has a destructor that takes care of cleaning up the memory automatically
Either of the latter two are preferred over the example below.
Open in new window