I have defined this struct :
typedef struct ethernet_header
{
UCHAR m_dest[6];
UCHAR m_source[6];
USHORT m_type;
} ETHER_HDR;
Then I used it in a function like this :
void SniffPacket(u_char* p_buffer, int p_size)
{
//Ethernet header
ETHER_HDR *l_ethHeader = (ETHER_HDR *)p_uffer;
//Do Something
//How to safely delete l_ethHeader;
}
Now I want to delete l_ethHeader before the function leaves. How to safely do it.
You don't!
You only delete what you new -- and there is no new here.
What you have essentially done is told the compiler to treat the p_buffer pointer value as though it was a pointer to your struct, but in doing so no extra memory was allocated. The same memory is being looked at - just with a different interpretation.
If you wish to keep the header you could do either this:
ETHER_HDR l_ethHeader = *(ETHER_HDR *)p_uffer;
which would allocate a header struct on the stack that would automatically be destroyed as it went out of scope.
Or this:
ETHER_HDR* l_ethHeader = new ETHER_HDR( *(ETHER_HDR *)p_uffer );
Which would allocate a struct on the heap which would need deleting later.
All else being equal you should opt for option 1, 'always favour the stack'.
Most coding style guide suggest that whoever allocate the memory is also responsible for deallocating it.
Your dealloocation depends on how it was allocated -- your code does not allocate anything, so I would not expect any deallocations either, but the function which called your function may need to deallocate.
If it was allocated using malloc -- then you simply free.
If your struct was allocated using "new" then you must use "delete" and make sure that your pointer is of the same type or a derived type (inheritance) as deconstructors may not fire correctly otherwise.
In your case the struct is a plain-old-data-type so it is impossible to say if it was allocated using malloc, new or if it is a stack variable -- the latter needs no deallocation at all as the return will take care of that.
Assuming your p_buffer is already allocated when you enter SniffPacket, you do not deallocate it in the function - as your function appears to be designed to "sniff", not to manage memory.
If it is not allocated (e.g. p_buffer is NULL or uninitialized) when you enter SniffPacket, then you are invoking undefined behavior in your cast, so anything you do after that is irrelevant.
It depends,
If you have allocated the memory using the new then you must use delete or delete[] (if it is an array), if you have allocated the memory using the malloc function then you must use free.
Regards
Related
My concern is whether or not the array should be deallocated. Here is an example:
typedef struct
{
int *values;
int length;
} a_struct;
void foo()
{
a_struct myStruct;
myStruct.values = new int[NUM];
delete[] myStruct.values; // Is this needed?
return;
}
My understanding is that myStruct (which is on the stack) will get deleted automatically upon the "return" statement. Does it delete "values" as well?
It does deallocate the pointer values, but not what it points to - after all, what does a_struct know about what you assigned to that pointer? Maybe it's a pointer to stuff allocated on the stack, or to an array shared with another struct.
So, yes, you need to manually deallocate it (although in modern C++ often "smart pointers" are used to manage memory).
No, it doesn't, you should delete it manually. myStruct going out of scope (and thus the myStruct.values member, i. e. the pointer being invalidated) has nothing to do with the dynamically allocated memory. The golden rule: if you call new[], always delete[] (same for new and delete).
Yes it is needed, the struct only stores the address of the array.
These days people would just store a std::vector<> (or if you just want an owning pointer to something a std::unique_ptr<>).
Nothing gets 'deleted'. The stack is popped. Period. As the struct doesn't have a destructor, nothing else happens.
I have a class pointer declaration:
MyClass* a;
In destruction method I have:
if (a)
{
delete a;
a= NULL;
}
I got a problem when delete the pointer a:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
What is the cause of the problem and how can I get rid of it?
With your current declaration:
MyClass* a;
a gets a random value. If you never give it a valid value later, such as:
a = new MyClass();
It will point to an unknown place in memory, quite probably not a memory area reserved for your program, and hence the error when you try to delete it.
The easiest way to avoid this problem is to give a a value when you declare it:
MyClass* a = new MyClass();
or, if you cannot give it a value when you declare it (maybe you don't know it yet), assign it to null:
MyClass* a = 0;
By the way, you can remove the test (if (a)) from your code. delete is a no-op on a null pointer.
Use smart pointer to free memory. delete in application code is always wrong.
unless you have initialized the pointer to something after this:
MyClass* a;
the pointer a will hold some random value. So your test
if (a) { }
will pass, and you attempt to delete some random memory location.
You can avoid this by initializing the pointer:
MyClass* a = 0;
Other options are that the object pointed to has been deleted elsewhere and the pointer not set to 0, or that it points to an object that is allocated on the stack.
As has been pointed out elsewhere, you could avoid all this trouble by using a smart pointer as opposed to a bare pointer in the first place. I would suggest having a look at std::unique_ptr.
How did you allocate the memory that a points to? If you used new[] (in order to create an array of MyClass), you must deallocate it with delete[] a;. If you allocated it with malloc() (which is probably a bad idea when working with classes), you must deallocate it with free().
If you allocated the memory with new, you have probably made a memory management error somewhere else - for instance, you might already have deallocated a, or you have written outside the bounds of some array. Try using Valgrind to debug memory problems.
You should use
MyClass* a = NULL;
in your declaration. If you never instantiate a, the pointer is pointing to an undefined region of memory. When the containing class destructor executes, it tries to delete that random location.
When you do MyClass* a; you declare a pointer without allocating any memory. You don't initialize it, and a is not necessarily NULL. So when you try to delete it, your test if (a) succeeds, but deallocation fails.
You should do MyClass* a = NULL; or MyClass* a(nullptr); if you can use C++11.
(I assume here you don't use new anywhere in this case, since you tell us that you only declare a pointer.)
int* f()
{
int *p = new int[10];
return p;
}
int main()
{
int *p = f();
//using p;
return 0;
}
Is it true that during stack destruction when function return it's value some compilers (common ones like VS or gcc were implied when I was told that) could try to automatically free memory pointed by local pointers such as p in this example? Even if it's not, would I be able to normally delete[] allocated memory in main? The problem seems to be that information about exact array size is lost at that point. Also, would the answer change in case of malloc and free?
Thank you.
Only Local variables are destroyed-released.
In your case p is "destroyed" (released) , but what what p points to, is not "destroyed" (released using delete[]).
Yes you can, and should/must use a delete[] on your main. But this does not imply using raw pointers in C++. You might find this e-book interesting : Link-Alf-Book
If you want to delete what a local variable points to when the function is "over" (out of scope) use std::auto_ptr() (only works for non-array variables though, not the ones which require delete[])
Also, would the answer change in case
of malloc and free?
Nope, but you should make sure that you do not mix free()/new/delete/malloc(). The same applies for new/delete[] and new[]/delete.
No, they won't free or delete what your pointer points to. They will only release the few bytes that the pointer itself occupies. A compiler that called free or delete would, I believe, violate the language standard.
You will only be able to delete[] memory in main if you a pointer to the memory, i.e., the result from f(). You don't need keep track of the size of the allocation; new and malloc do that for you, behind the scenes.
If you want memory cleaned up at function return, use a smart pointer such as boost::scoped_ptr or boost::scoped_array (both from the Boost collection of libraries), std::auto_ptr (in the current C++ standard, but about to be deprecated) or std::unique_ptr (in the upcoming standard).
In C, it's impossible to create a smart pointer.
Is it true that during stack destruction when function return it's value some compilers (common ones like VS or gcc were implied when I was told that) could try to automatically free memory pointed by local pointers such as p in this example?
Short Answer: No
Long Answer:
If you are using smart pointers or container (like you should be) then yes.
When the smart pointer goes out of scope the memory is released.
std::auto_ptr<int> f()
{
int *p = new int;
return p; // smart pointer credated here and returned.
// p should probably have been a smart pointer to start with
// But feeling lazy this morning.
}
std::vector<int> f1()
{
// If you want to allocate an array use a std::vector (or std::array from C++0x)
return std::vector<int>(10);
}
int main()
{
std::auto_ptr<int> p = f();
std::vector<int> p1 = f1();
//using p;
return 0; // p destroyed
}
Even if it's not, would I be able to normally delete[] allocated memory in main?
It is normal to make sure all memory is correctly freed as soon as you don't need it.
Note delete [] and delete are different so be careful about using them.
Memory allocated with new must be released with delete.
Memory allocated with new [] must be released with delete [].
Memory allocated with malloc/calloc/realloc must be released with free.
The problem seems to be that information about exact array size is lost at that point.
It is the runtime systems problem to remember this information. How it is stored it is not specified by the standard but usually it is close to the object that was allocated.
Also, would the answer change in case of malloc and free?
In C++ you should probably not use malloc/free. But they can be used. When they are used you should use them together to make sure that memory is not leaked.
You were misinformed - local variables are cleaned up, but the memory allocated to local pointers is not. If you weren't returning the pointer, you would have an immediate memory leak.
Don't worry about how the compiler keeps track of how many elements were allocated, it's an implementation detail that isn't addressed by the C++ standard. Just know that it works. (As long as you use the delete[] notation, which you did)
When you use new[] the compiler adds extra bookkeeping information so that it knows how many elements to delete[]. (In a similar way, when you use malloc it knows how many bytes to free. Some compiler libraries provide extensions to find out what that size is.)
I haven't heard of a compiler doing that, but it's certainly possible for a compiler to detect (in many cases) whether the allocated memory from the function isn't referenced by a pointer anymore, and then free that memory.
In your case however, the memory is not lost because you keep a pointer to it which is the return value of the function.
A very common case for memory leaks and a perfect candidate for such a feature would be this code:
int *f()
{
int *p = new int[10];
// do something that doesn't pass p to external
// functions or assign p to global data
return p;
}
int main()
{
while (1) {
f();
}
return 0;
}
As you can notice, the pointer to the allocated memory is lost and that can be detected by the compiler with absolute certainty.
Having structs like
struct ifoo_version_42 {
int x, y, z;
char *imageData;
};
where imageData is something like imageData = new char[50000];
Can we perform something like:
template< typename T >
void del( T a ) // we promise to use this only on C Plain Old data structs=)
{
delete a;
}
on this structure an will it be enough to clean memory form if?
Deleting the struct does not recursively delete any pointers in it, and hence doesn't free the array of char pointed to by imageData.
I'm also a bit confused by your use of delete[]. You can free an array (allocated with new[]) using delete[], or free a single object (allocated with new) using delete. You can't mix them, and you don't say how you're allocating one or more instances of ifoo_version_42. For example the following has undefined behavior:
ifoo_version_42 *x = new ifoo_version_42;
del(x);
The following is OK:
ifoo_version_42 *x = new ifoo_version_42[1];
del(x);
This function template would also "work" on non-POD types. It's literally no different from invoking delete[] a; directly.
However, this won't delete the memory associated with imageData. That's typically the sort of thing you do in a destructor.
If you perform your del function on an ifoo_version_42, then the memory block pointed to by data will not be freed; neither delete nor delete[] work recursively.
delete[] is meant to be used for freeing arrays; that is, if you allocated imageData with new[], then it should be freed with delete[].
delete is meant to be used for freeing single objects: If you e.g. allocated a ifoo_version_42 with new, then you should free it with delete.
(Also, never use delete for something allocated with malloc(), or free() with something allocated with new.)
One further suggestion: Learn the RAII idiom and use smart pointer classes provided by the STL or Boost libraries; these go a long way towards helping you with correct memory management.
I know that memory alloced using new, gets its space in heap, and so we need to delete it before program ends, to avoid memory leak.
Let's look at this program...
Case 1:
char *MyData = new char[20];
_tcscpy(MyData,"Value");
.
.
.
delete[] MyData; MyData = NULL;
Case 2:
char *MyData = new char[20];
MyData = "Value";
.
.
.
delete[] MyData; MyData = NULL;
In case 2, instead of allocating value to the heap memory, it is pointing to a string literal.
Now when we do a delete it would crash, AS EXPECTED, since it is not trying to delete a heap memory.
Is there a way to know where the pointer is pointing to heap or stack?
By this the programmer
Will not try to delete any stack memory
He can investigate why does this ponter, that was pointing to a heap memory initially, is made to refer local literals? What happened to the heap memory in the middle? Is it being made to point by another pointer and delete elsewhere and all that?
Is there a way to know where the pointer is pointing to heap or stack?
You can know this only if you remember it at the point of allocation. What you do in this case is to store your pointers in smart pointer classes and store this in the class code.
If you use boost::shared_ptr as an example you can do this:
template<typename T> void no_delete(T* ptr) { /* do nothing here */ }
class YourDataType; // defined elsewhere
boost::shared_ptr<YourDataType> heap_ptr(new YourDataType()); // delete at scope end
YourDataType stackData;
boost::shared_ptr<YourDataType> stack_ptr(&stackData, &no_delete); // never deleted
As soon as you need that knowledge you have already lost. Why? Because then even if you omit the wrong delete[], you still have a memory leak.
The one who creates the memory should always be the one who deletes it. If at some occasion a pointer might get lost (or overwritten) then you have to keep a copy of it for the proper delete.
There is no way in Standard C++ of determining whether a pointer points to dynamically allocated memory or not. And note that string literals are not allocated on the stack.
As most of the users said here there's no standard way to discover which memory you're dealing with.
Also, as many users pointed out, it;s a kinda perverted situation where you pass a pointer to a function which should delete it automatically if it's allocated on heap.
But if you insist, nevertheless there are some ways to discover which memory belongs to which type.
You actually deal with 3 types of memory
Stack
Heap
Global
For instance:
char* p = new char[10]; // p is a pointer, points to heap-allocated memory
char* p = "Hello, world!"; // p is a pointer, points to the global memory
char p[] = "Hello, world!"; // p is a buffer allocated on the stack and initialized with the string
Now let's distinguish them. I'll describe this in terms of Windows API and x86 assembler (since this is what I know :))
Let's start from stack memory.
bool IsStackPtr(PVOID pPtr)
{
// Get the stack pointer
PBYTE pEsp;
_asm {
mov pEsp, esp
};
// Query the accessible stack region
MEMORY_BASIC_INFORMATION mbi;
VERIFY(VirtualQuery(pEsp, &mbi, sizeof(mbi)));
// the accessible stack memory starts at mbi.BaseAddress and lasts for mbi.RegionSize
return (pPtr >= mbi.BaseAddress) && (pPtr < PBYTE(mbi.BaseAddress) + mbi.RegionSize);
}
If the pointer is allocated on the stack of another thread you should get its stack pointer by GetThreadContext instead of just taking the EIP register value.
Global memory
bool IsGlobalPtr(PVOID pPtr)
{
MEMORY_BASIC_INFORMATION mbi;
VERIFY(VirtualQuery(pPtr, &mbi, sizeof(mbi)));
// Global memory allocated (mapped) at once for the whole executable
return mbi.AllocationBase == GetModuleHandle(NULL);
}
If you're writing a DLL you should put its module handle (which is actually its base mapping pointer) instead of GetModuleHandle(NULL).
Heap
Theoretically you may assume that if the memory is neither global nor stack - it's allocated on heap.
But there's is actually a big ambiguity here.
You should know that there're different implementations of the heap (such as raw Windows heap accessed by HeapAlloc/HeapFree, or CRT-wrapped malloc/free or new/delete).
You may delete such a block via delete operator only if you know for sure it was either stack/global pointer or it was allocated via new.
In conclusion:
It's a kinda pervert trick. Should not be used generally. Better to provide some extra information with the pointer which tells how to release it.
You can only use it if you know for sure on which heap the memory was allocated (in case it's a heap memory).
I think there is no (easy) way how to tell where the memory is allocated (you might be able to determine it using a debugger, perhaps, but that is obviously not what you want). The bottom line is: never do the thing you did in case 2.
In case 2, MyData = "Value" causes a memory leak since there is no longer a reference to the memory returned from new.
There is no easy way or standard way for doing this. You can intercept the heap allocation function(s) and put each memory allocated zone in a list. Your "IsHeap" function should check if the zone passed to the function is the one from the list. This is just a hint - it is almost impossible to do this in a cross-platform manner.
But then again - why would you need that?