Dynamic memory management

Hello.My Problem is that if I new an object in a function, say to create a character string on the heap, how to delete it long after the function returns?
Last edited on
keep a pointer at it
I say after the function exits;then the pointer goes out of scope, doesn't it?
You can return things from the function...
so what?the pointer goes out of scope
I think this is what you're looking for.
http://cplusplus.com/forum/general/28422/

-Albatross
closed account (EzwRko23)
Before the pointer gets out of scope, delete the object.
You can't delete it **after** the function returns if you don't return the pointer.
Last edited on
Functions returning a pointer to a dynamically allocated memory depend heavily on the code that call the function to do the proper clean-up after finish using it. What if after calling the function, the outside code forget to do a delete or free ?

There is no easy solution but Scott Meyers propose to have something called auto_ptr concept which is a class that "wrap" the pointer ? Then when that auto_ptr object is destructed say out of scope for e.g, inside the auto_ptr destructor it will delete and free the pointer dynamically allocated memory.

Somehow I find the whole auto_ptr concept an overkill. I will still go by the plain old simpler way of making it a discipline to free those functions that return me a pointer when I finish using it :)

closed account (D80DSL3A)
Aren't we just talking about doing this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>// for use of cin, cout

using namespace std;

char* NewString(char* pch)
{	
	// allocate for new string
	int n = 1 + strlen(pch);
	char* pchLocal = new char[ n ];
	strcpy_s(pchLocal, n*sizeof(char), pch);

	return(pchLocal);
}

int main()
{		
	char* str1 = NewString("New string here!");	
	cout << str1 << endl;				
	delete str1;	

	system("PAUSE");// OK for "casual" use?
	return 0;
}


This program seems to run fine and does not trigger any heap corruption or other errors. I think that the char* returned by NewString() is what Bazzy was referring to.
You seem to be misunderstanding scopes. The pointer goes out of scope, yes. But the dynamically allocated object doesn't. If you return a copy of the pointer (which is what a normal return-statement does), you can still use the object. Just remember to delete it, too.

That said, this way is possible and 100% legit, but it's not the nicest way to do this and most certainly not the most leak-free way.
closed account (D80DSL3A)
Not leak-free? Is this because the programmer might forget to include line 19?

In response to sohguanh's post about using a class to "wrap" a pointer being used for dynamic memory allocation of a character array, how about this? The DAD class below automates use of its char* pwic data member so the programmer need not get his fingers dirty with "new" or "delete" while using it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// A class for using dynamic character arrays
#include <iostream>
using namespace std;

class DAD
{
public:
	char* pwic;// pointer to string in class

	char* assignWord(char* pch);// return pointer to new string
	DAD(char* pch = NULL);// overloaded. Pass a char* now or call copyWord() later
	~DAD();// destructor
};
// will delete previous string and allocate for new
char* DAD::assignWord(char* pch)
{
	if( pwic != NULL )// delete previously allocated array
	{
		delete [] pwic;
		pwic = NULL;
	}
	// allocate for new string
	int n = 1 + strlen(pch);
	pwic = new char[ n ];
	strcpy_s(pwic, n*sizeof(char), pch);
	cout << "pwic deleted + new again" << endl;

	return(pwic);
}
// constructor - allocates char array and copies to it
DAD::DAD(char* pch )
{	
	if( pch != NULL )
	{
		int n = 1 + strlen(pch);
		pwic = new char[ n ];
	    strcpy_s(pwic, n*sizeof(char), pch);
		cout << "DAD constructor here" << endl;
	}
	else
		pwic = NULL;// no string supplied to constructor
}
// destructor - deletes char array
DAD::~DAD()
{	
	if( pwic != NULL )	
		delete [] pwic;
	
	cout << "DAD destructor was here" << endl;
}

void ShowMessage(void)
{
	DAD localString("Hello from local DAD");
	cout << localString.pwic << endl;

	localString.assignWord("How's the weather in main()?");
	cout << localString.pwic << endl;

	return;// ~DAD() called on localString here
}

int main()
{	  	
	ShowMessage();// I want call to ~DAD() to show so I'll use a local DAD
	DAD mainDAD;// just checking that it's safe to call ~DAD() on an uninitialized DAD

	system("PAUSE");

	return 0;
}


Last edited on
In this case wouldn't you need to do this? After all you are dynamically allocating an array of characters.

delete [] str1;

Incidentally that is why you should avoid doing it this way. It is very error prone. fun2code's initial example is incorrect. It isn't so bad in a simple program but as you can see, even in a simple program mistakes can be made. The program might run fine but that doesn't mean that it is correct. A failure to use the correct form of delete results in undefined behavior so it is possible that in a more complex program that technique could result in the program crashing or exhibiting unexpected behavior.
Last edited on
Last edited on
sohguanh wrote:
There is no easy solution but Scott Meyers propose to have something called auto_ptr concept which is a class that "wrap" the pointer ? Then when that auto_ptr object is destructed say out of scope for e.g, inside the auto_ptr destructor it will delete and free the pointer dynamically allocated memory.


auto_ptr doesn't work for arrays. For dynamic arrays use std::string or one of the other sequence containers such as vector, deque, or list.
closed account (D80DSL3A)
Kempofighter, you are right. My line #19 needs to be delete [] str1. Point taken about the method being error-prone.
I'm not sure what fun2code's latest example was designed to show other than that a wrapper class makes it a little easier since the delete has to be done only in one or two places instead of by the caller. However if you write your own wrapper you still have to remember that and provide a convenient and useful interface. This is why we have std::string in the C++ STL.
closed account (D80DSL3A)
That is all that my example was meant to show. Clearly, std::string is a superior tool. Sometimes I build things like the DAD class as an exercise, just to see if it will work.

That is all that my example was meant to show. Clearly, std::string is a superior tool. Sometimes I build things like the DAD class as an exercise, just to see if it will work.


Hi your DAD class could overload some operator to make it more intuitive to use maybe :) In the auto_ptr reference implementation, Scott Meyers also overload some operators so that when we have a variable like auto_ptr, we use it as though it is a pointer variable but we don't have to worry to delete or free etc issues.
Topic archived. No new replies allowed.