Reputation: 805
Trying to see the proper way to free memory, and I can't find a definitive answer. I'm sure it's out there, but I can't seem to find it and I'm a bit confused.
Here's what I'm doing. I create a new sStructUsers from sUsers, then I allocate memory for the username
struct sStructUsers
{
TCHAR *sName;
};
sStructUsers *sUsers = new sStructUsers[TOTALUSERS]();
// Allocate memory for the TCHARs in sStruct
for (INT k = 0; k < TOTALUSERS; k++)
{
sUsers [k].sName = (TCHAR*)calloc(128,sizeof(TCHAR))
}
Next, I do whatever work I need to do with the sName member
// do work here
Now, to cleanup, do I do this:
delete[] sUsers;
or do I do this?
for (INT k = 0; k < TOTALUSERS; k++)
{
free(sUsers[k].sName);
}
delete[] sUsers?
I'm not sure if I need to free the memory or if delete[] would take care of it?
Upvotes: 0
Views: 1252
Reputation: 659
Each allocation should be deallocated. By some code. As sklott wrote, there are tools (containers and other classes) that do the work for you. If some other code does not do it, then your code should do the deallocation.
In short, you should call both free(sUsers[k].sName)
and delete[] sUsers
. As it stands, deleting[] sStructUsers
s will not free pointers inside it.
(You could also modify sStructUsers
so that its destructor does the deallocation, either directly or through a smart pointer.)
(To answerers and commenters who posted "never mix up new/delete with malloc/free", please kindle bash me with comments explaining why. It is always important to understand the rationale behind advice and best practices. Update: obviously you must not mix new+free, or malloc+delete, etc.; such functions must be properly paired lest you get heap corruption and leaks. The finer question is why not use new+delete for some allocations and malloc/calloc+free for others [finer still: CoTaskMemAlloc(), HeapAlloc(), VirtualAlloc() or other plataforms functions...]. )
Upvotes: 1
Reputation: 2849
Don't use new
at all if you can help it. In modern C++ in most cases new
is not needed.
You can use std::vector
, std::array
, std::string
(std::basic_string<TCHAR>
maybe), std::unique_ptr
or std::shared_ptr
.
If you feel like you really need to use new
, make special class which will handle this. I.e. for example make new
in constructor and delete
in destructor.
And of course, as was said in comments, never mix up new/delete with malloc/free. There is no need to use these functions in C++ at all, since this is remnants of C.
Edit: Added example, how this can be handled by class itself.
struct sStructUsers
{
const int MAX_NAME_SIZE = 128;
sStructUsers()
{
sName = new TCHAR[MAX_NAME_SIZE];
}
~sStructUsers()
{
delete sName;
}
TCHAR *sName;
};
Then you don't need any initialization/cleanup when using this class.
Note that you usually you don't need to do even this, you can define you class as this:
struct sStructUsers
{
std::basic_string<TCHAR> sName;
};
And have full string
functionality for free. Or like this, if you really need a pointer:
struct sStructUsers
{
const int MAX_NAME_SIZE = 128;
sStructUsers() : sName(new TCHAR[MAX_NAME_SIZE]) {}
std::unique_ptr<TCHAR[]> sName;
};
Or, as I mentioned earlier, use other standard containers.
Upvotes: 5
Reputation: 10756
The comments and answers that are advising more preferable containers, more idiomatic C++, and more modern practices are all fine and well.
But your immediate question is answered by your second option
for (INT k = 0; k < TOTALUSERS; k++)
{
free(sUsers[k].sName);
}
delete[] sUsers;
That will not leak memory. However your first option will leak because a mere delete[]
of the array will not deallocate the heap memory of its elements.
In short, use delete[]
for every new[]
, and free
for every calloc
.
(Only then perhaps refactor to be closer to C++ than a mix of C and C++)
Upvotes: 1