Should pointers to "raw" resources be zeroed in destructors? - c++

When I wrap "raw" resources in a C++ class, in destructor code I usually simply release the allocated resource(s), without paying attention to additional steps like zeroing out pointers, etc.
e.g.:
class File
{
public:
...
~File()
{
if (m_file != NULL)
fclose(m_file);
}
private:
FILE * m_file;
};
I wonder if this code style contains a potential bug: i.e. is it possible that a destructor is called more than once? In this case, the right thing to do in the destructor would be to clear pointers to avoid double/multiple destructions:
~File()
{
if (m_file != NULL)
{
fclose(m_file);
m_file = NULL; // avoid double destruction
}
}
A similar example could be made for heap-allocated memory: if m_ptr is a pointer to memory allocated with new[], is the following destructor code OK?
// In destructor:
delete [] m_ptr;
or should the pointer be cleared, too, to avoid double destruction?
// In destructor:
delete [] m_ptr;
m_ptr = NULL; // avoid double destruction

No. It is useful if you have a Close() function or the like:
void Close()
{
if (m_file != NULL)
{
fclose(m_file);
m_file = NULL;
}
}
~File()
{
Close();
}
This way, the Close() function is idempotent (you can call it as many times as you want), and you avoid one extra test in the destructor.
But since destructors in C++ can only be called once, assigning NULL to pointers there is pointless.
Unless, of course, for debuggin-purposes, particularly if you suspect a double-delete.

If a destructor is called more than once, you already have undefined behavior. This will also not affect clients that may have a pointer to the resource themselves, so this is not preventing a double delete. A unique_ptr or scoped_ptr seem to be better solutions to me.

In a buggy application (for example, improper use of std::unique_ptr<> can result in two std::unique_ptr<> holding the same raw pointer), you can end up with a double delete, as the second one goes out of scope.
We care about these bad cases - otherwise, what's the point of discussing setting a pointer to nullptr in the destructor? It's going away anyways!
Hence, in this example, at least, it would be better to let the program seg-fault inside a debugger during a unit-test, so you can trace the real cause of the problem.
So, in general, I don't find setting pointers to nullptr to be particularly useful for memory management.
You could do it, but a more robust alternative is to do unit tests and to judiciously use a memory checker like valgrind.
After all, with some memory errors, your program can seemingly run ok many times, until it crashes unexpectedly - much safer to do quality assurance with a memory checker, especially as your program gets larger, and memory errors become less obvious.

Related

How to prevent Dangling Pointer in C++ Legacy Code

Is it always wise to use NULL after a delete in legacy code without any smartpointers to prevent dangling pointers? (bad design architecture of the legacy code excluded)
int* var = new int(100);
delete var;
var = NULL;
Does it also make sense in destructors?
In a getter, does it make sense to test for NULL in second step?
Or is it undefinied behavier anyway?
Foo* getPointer() {
if (m_var!=NULL) { // <-is this wise
return m_var;
}
else {
return nullptr;
}
}
What about this formalism as an alternative? In which cases will it crash?
Foo* getPointer() {
if (m_var) { // <-
return m_var;
}
else {
return nullptr;
}
}
(Edit) Will the code crash in example 3./4. if A. NULL is used after delete or B. NULL is not used after delete.
Is it always wise to use NULL after a delete in legacy code without any smartpointers to prevent dangling pointers? (bad design architecture of the legacy code excluded)
int* var = new int(100);
// ...
delete var;
var = NULL;
Only useful if you test var afterward.
if scope ends, or if you set other value, setting to null is unneeded.
Does it also make sense in destructors?
nullify members in destructor is useless as you cannot access them without UB afterward anyway. (but that might help with debugger)
In a getter, does it make sense to test for NULL in second step? Or is it undefinied behavier anyway?
[..]
[..]
if (m_var != NULL) and if (m_var) are equivalent.
It is unneeded, as, if pointer is nullptr, you return nullptr,
if pointer is not nullptr, you return that pointer, so your getter can simply be
return m_var;
Avoid writing code like this
int* var = new int(100);
// ... do work ...
delete var;
This is prone to memory leaks if "do work" throws, returns or otherwise breaks out of current scope (it may not be the case right now but later when "do work" needs to be extended/changed). Always wrap heap-allocated objects in RAII such that the destructor always runs on scope exit, freeing the memory.
If you do have code like this, then setting var to NULL or even better a bad value like -1 in a Debug build can be helpful in catching use-after-free and double-delete errors.
In case of a destructor:
Setting the pointer to NULL in a destructor is not needed.
In production code it's a waste of CPU time (writing a value that will never be read again).
In debug code it makes catching double-deletes harder. Some compilers fill deleted objects with a marker like 0xDDDDDDDD such that a second delete or any other dereference of the pointer will cause a memory access exception. If the pointer is set to NULL, delete will silently ignore it, hiding the error.
This question is really opinion-based, so I'll offer some opinions ... but also a justification for those opinions, which will hopefully be more useful for learning than the opinions themselves.
Is it always wise to use NULL after a delete in legacy code without any smartpointers to prevent dangling pointers? (bad design architecture of the legacy code excluded)
Short answer: no.
It is generally recommended to avoid raw pointers whenever possible. Regardless of which C++ standard your code claims compliance with.
Even if you somehow find yourself needing to use a raw pointer, it is safer to ensure the pointer ceases to exist when no longer needed, rather than setting it to NULL. That can be achieved with scope (e.g. the pointer is local to a scope, and that scope ends immediately after delete pointer - which absolutely prevents subsequent use of the pointer at all). If a pointer cannot be used when no longer needed, it cannot be accidentally used - and does not need to be set to NULL. This also works for a pointer that is a member of a class, since the pointer ceases to exist when the containing object does i.e. after the destructor completes.
The idiom of "set a pointer to NULL when no longer needed, and check for NULL before using it" doesn't prevent stupid mistakes. As a rough rule, any idiom that requires a programmer to remember to do something - such as setting a pointer to NULL, or comparing a pointer to NULL - is vulnerable to programmer mistakes (forgetting to do what they are required to do).
Does it also make sense in destructors?
Generally speaking, no. Once the destructor completes, the pointer (assuming it is a member of the class) will cease to exist as well. Setting it to NULL immediately before it ceases to exist achieves nothing.
If you have a class with a destructor that, for some reason, shares the pointer with other objects (i.e. the value of the pointer remains valid, and presumably the object it points at, still exist after the destructor completes) then the answer may be different. But that is an exceedingly rare use case - and one which is usually probably better avoided, since it becomes more difficult to manage lifetime of the pointer or the object it points at - and therefore easier to introduce obscure bugs. Setting a pointer to NULL when done is generally not a solution to such bugs.
In a getter, does it make sense to test for NULL in second step? Or is it undefinied behavier anyway?
Obviously that depends on how the pointer was initialised. If the pointer is uninitialised, even comparing it with NULL gives undefined behaviour.
In general terms, I would not do it. There will presumably be some code that initialised the pointer. If that code cannot appropriately initialise a pointer, then that code should deal with the problem in a way that prevents your function being called. Examples may include throwing an exception, terminating program execution. That allows your function to safely ASSUME the pointer points at a valid object.
What about this formalism as an alternative? In which cases will it crash?
The "formalism" is identical to the previous one - practically the difference is stylistic. In both cases, if m_var is uninitialised, accessing its value gives undefined behaviour. Otherwise the behaviour of the function is well-defined.
A crash is not guaranteed in any circumstances. Undefined behaviour is not required to result in a crash.
If the caller exhibits undefined behaviour (e.g. if your function returns NULL the caller dereferences it anyway) there is nothing your function can do to prevent that.
The case you describe remains relatively simple, because the variable is described in a local scope.
But look for example at this scenario:
struct MyObject
{
public :
MyObject (int i){ m_piVal = new int(i); };
~MyObject (){
delete m_piVal;
};
public:
static int *m_piVal;
};
int* MyObject::m_piVal = NULL;
You may have a double free problem by writing this:
MyObject *pObj1 = new MyObject(1);
MyObject *pObj2 = new MyObject(2);
//...........
delete pObj1;
delete pObj2; // You will have double Free on static pointer (m_piVal)
Or here:
struct MyObject2
{
public :
MyObject2 (int i){ m_piVal = new int(i); };
~MyObject2 (){
delete m_piVal;
};
public:
int *m_piVal;
};
when you write this:
MyObject2 Obj3 (3);
MyObject2 Obj4 = Obj3;
At destruction, you will have double Free here because Obj3.m_piVal = Obj4.m_piVal
So there are some cases that need special attention (Implement : smart pointer, copy constructor, ...) to manage the pointer

Do I have to delete pointer even if it is in function stack?

always delete pointer even if it is just in function call stack?
Isn't it disappeared when function stack released?
// just Simple class
class CSimple{
int a;
}
// just simple function having pointer.
void simpleFunc(){
CSimple* cSimple = new CSimple();
cSimple->a = 10;
//.. do sth
delete cSimple; // <<< Always, do I have to delete 'cSimple' to prevent the leak of memory?
}
void main(){
for( int =0 ; i< 10 ; i++){
simpleFunc();
}
}
when function stack released?
It is true that "CSimple *csimple" goes away when the function returns.
However, there's a big difference between the pointer, and what it's pointed to.
When a pointer object gets destroyed, nothing happens to whatever the pointer is pointing to. There isn't just one, but two objects here:
The pointer.
What it's pointing to.
In this case, the pointer is pointing to an object in dynamic scope that was created with new.
Nothing is going to happen to this object, otherwise, so you will leak memory.
Therefore, this object needs to be deleted.
After you understand, and fully wrap your brain around this concept, your next step will be to open your C++ book to the chapter that talks about the std::unique_ptr and std::shared_ptr classes, which will take care of these pesky details, for you. You should learn how to use them. Modern C++ code rarely needs to delete something; rather these smart pointers do all the work.
Yes.
On scope exit (ex. when function exists or block { ... } finishes), all objects created on stack will be destroyed and memory will be freed.
This applies to your case, ie. the pointer will be destroyed and memory occupied by the pointer will be freed. The object pointed by the pointer will not be cleared.
This is a common problem and a nightmare when you deal with multiple flow paths (if-else ladders, many return statements) and exceptions.
To solve this problem, we employ 2 main strategies:
RAII
Smart pointers (std::unique_ptr, boost::scoped_ptr, legacy std::auto_ptr, etc).
RAII - without academic consideration - is just creating object on stack, like this:
{
std::string s;
fancy_object obj;
}
When we exit he scope, obj and s destructors will be called duing stack unwinding. Compiler ensures this for all flow paths and will keep proper order of deallocations for us.
If you need to allocate memory on heap, using new, use a smart pointer.
int foo()
{
std::unique_ptr<Object> o(new Object);
... some more code ...
if( something ) { return -1 }
... some more code ...
if( something_else ) { return -2 }
else { not yet }
return 0;
}
As you can see, we can leave the scope using 3 "exists". Normally, you'd need to clear your memory in all cases, which is prone to human errors.
Instead of clearing the object manually in all 3 palces, we rely on automatic destructor call for objects created on stack. Compiler will figure it out. When we leave the scope, std::unique_ptr destructor will be called, calling delete on Object.
Don't be affraid of smart poiners. They are not "slow", "bloat" or other nonsense. Smart poiners are designed to have no overhead on access, adding extra security.
Very similar technique is used for locks. Check out std::lock_guard class.
Yes, you must delete the data that is being pointed to.
The pointer itself is on the stack and does not need to be deleten.
You can, however, store cSimple on the stack, then you don't have to delete it:
void simpleFunc(){
CSimple cSimple; // no new
cSimple.a = 10; // "." instead of "->"
//.. do sth
// no deletion
}

Can initialization `int * p = malloc(1000);` also be dealt in RAII style?

What I understand from RAII is whenever you need to allocate memory manually with new etc. you need to free it too. So, instead of freeing it manually, you should create classes with constructor and destructor to do the job.
So, what are the following people talking about?
From: The meaning of the term - Resource Acquisition Is Initialization
The problem is that int * p = malloc(1000); is also initialization of an (integer) object, but it's not the kind of initialization we mean in the context of RAII.
...
#Fred: Indeed. int* is not a RAII type because it doesn't do cleanup. So it's not what RAII means, even though it is what RAII literally says.
Well, I know malloc is used in C, and new is used in C++.
Using malloc per se is not RAII because the resources are not freed when the variable goes out of scope, causing leaks of memory. You can make it RAII if you wrap this inside a class and free the resources in the destructor, because local class instances do die when they go out of scope. However, it should be noted what is being discussed here: the int * type is not RAII, and if you enclose it in a RAII type it still isn't. The wrapper doesn't make it RAII, so the RAII type here is the wrapper, not the pointer itself.
As requested in the comments: RAII stands for Resource Acquisition Is Initialisation and it's a design paradigm that combines the allocation of resources with the initialisation and destruction of objects. You don't seem far from understanding it: when an object is instantiated it allocates all the necessary resources (memory, file descriptors, streams, and so on) and frees them when it goes out of scope or the object is otherwise destructed. This is a common paradigm in C++ because C++ classes are RAII (that is, they die when they go out of scope) and as such it's easy to guarantee proper cleanup. The obvious upside being that you don't need to worry about manual cleanup and tracking variable lifetime.
On a related note, notice that this refers to stack allocation, not heap. What this means is that whatever the means you use for allocation (new/malloc vs delete/free) it still isn't RAII; memory that is allocated dynamically does not get magically freed, that's a given. When a variable is allocated on the stack (local variables) they are destroyed when the scope dies.
Example:
class MyObject
{
public:
MyObject()
{
// At this point resources are allocated (memory, files, and so on)
// In this case a simple allocation.
// malloc would have been just as fine
this->_ptr = new int;
}
~MyObject()
{
// When the object is destructed all resources are freed
delete this->_ptr;
}
private:
int * _ptr;
};
The previous sample code implements a RAII wrapper over a native pointer. Here's how to use it:
void f()
{
MyObject obj;
// Do stuff with obj, not including cleanup
}
In the previous example the int pointer is allocated when the variable is instantiated (at declaration time) and freed when the f call terminates, causing the variable to go out of scope and calling its destructor.
Note: As mentioned in the comments by Jarod42 the given example does not conform to the rule of 3 or the rule of 5, which are common thumb rules in C++. I would rather not add complexity to the given example, and as such I'll complete it here. These rules indicate that, if a method from a given set is implemented, then all methods of the set should be implemented, and those methods are the copy and move constructors, the assignment and move operators, and the destructor. Notice at first that this is a general rule, which means that is not mandatory. For instance, immutable objects should not implement assignment and move operators at all. In this case, if the object is to implement these operators it would probably imply reference counting, as multiple copies of the resource exist the destructor must not free the resources until all copies are destroyed. I believe that such an implementation would fall out of scope and as such I'm leaving it out.
By example
NOT RAII:
void foo()
{
int* p = malloc(sizeof(int) * N);
// do stuff
free(p);
}
also NOT RAII:
void foo()
{
int* p = new int[N];
// do stuff
delete[] p;
}
RAII:
struct MyResourceManager
{
int* p;
MyResourceManager(size_t n) : p(malloc(sizeof(int) * n)) { }
~MyResourceManager() { free(p); }
};
void foo()
{
MyResourceManager resource(N);
// doing stuff with resource.p
}
Also RAII (better):
struct MyResourceManager
{
int* p;
MyResourceManager(size_t n) : p(new int[n]) { }
~MyResourceManager() { delete[] p; }
};
void foo()
{
MyResourceManager resource(N);
// doing stuff with resource.p
}
Also RAII (best for this use case):
void foo()
{
std::unique_ptr<int[]> p(new int[N]);
// doing stuff with p
}
RAII is not use of operator new nor is it use of malloc().
It essentially means that, in the process of initialising an object, all resources that object needs to function are allocated. The counterpart requirement is that, in the process of destroying the object, that the resources it has allocated are released.
The concept applies to memory (most commonly), but also to any other resource that needs to be managed - file handles (opened in initialisation, closed when done), mutexes (grabbed in initialisation, released when done), communication ports, etc etc.
In C++, RAII is typically implemented by performing initialisation in constructors of an object, and the release of resources is done in the destructor. There are wrinkles such as other member functions possibly reallocating (e.g. resizing a dynamically allocated array) - in those cases, the member functions must ensure they do things in a way to ensure all resources allocated are appropriately released when the destructor is done. If there are multiple constructors, they need to do things consistently. You'll see this described as something like the constructor setting a class invariant (i.e. that resources are allocated correctly), member functions maintaining that invariant, and the destructor being able to clean up because the invariant is maintained.
The advantage of RAII - if done right - is that non-static variable lifetime is managed by the compiler (when an object goes out of scope, its destructor is invoked). So, the resources will be cleaned up correctly.
However, the requirement is always that the destructor does the cleanup (or that data members of the class have their own destructors that do the required cleanup). If constructor initialises an int * using malloc(), then it is not enough to assume the destructor will clean up - the destructor must pass that pointer to free(). If you don't do that, the C++ compiler will not magically find some way to release the memory for you (the pointer will no longer exist when the destructor is done, but the allocated memory it pointed to will not be released - so the result is a memory leak). C++ does not inherently use garbage collection (which is a trap for people used to garbage collected languages assuming that garbage collection will occur).
And it is undefined behaviour to use malloc() to allocate memory, and operator delete in any form to release it.
It is generally preferable to not use malloc() and free() in C++, because they do not work well with object construction and destruction (invoking constructors and destructors). Use operator new instead (and for whatever form of operator new you use, use the corresponding operator delete). Or, better yet, use standard C++ containers (std::vector, etc) as much as possible to avoid the need to worry about manually releasing memory you allocate.
Destruction of int* doesn't release the resources. It isn't safe to just let it go out of scope, so it isn't RAII.
The int * could be be a member of a class that deletes the int* in its destructor, which is essentially what unique_ptr of an int does. You make things like this RAII by wrapping them in code that encapsulates the deletion.
The discussion is about code that literally does initialization upon resource acquisition, but doesn't follow the RAII design.
In the shown example with malloc, 1000 bytes of memory are allocated (resource allocation) and a variable p (pointer to int) is initialized with the result (initialization). However, this is obviously not an example of RAII, because the object (of type int *) doesn't take care of the acquired resource in its destructor.
So no, malloc itself can not be RAII in some situations, it is an example of non-RAII code that nevertheless does "Initialization on Resource Acquisition" which might be confusing for new c++ programmers on first glance.
In C++, unique_ptr represents a pointer that "owns" the thing it points to. You can supply the release function as second argument:
std::unique_ptr<int[], std::function<void(void*)>>
p( (int *)malloc(1000 * sizeof(int)), std::free );
Of course, there's not much reason to do this instead of just using new (when the default deleter delete will do the right thing).
Yes, you can deal with int * p = malloc(1000); using the RAII paradigm. Smart pointers and std::vector use a very similar technique though they don't probably use malloc and prefer to use new instead.
Here's a very simplistic look at what one can do with malloc. MyPointer is far from being useful in a real application. Its only purpose is to demonstrate the principle of RAII.
class MyPointer
{
public:
MyPointer(size_t s) : p(malloc(s)) {}
~MyPionter() { free(p); }
int& operator[](size_t index) { return p[index]; }
private:
int* p;
};
int main()
{
// By initializing ptr you are acquiring resources.
// When ptr gets destructed, the resource is released.
MyPointer ptr(1000);
ptr[0] = 10;
std::cout << ptr[0] << std::endl;
}
The core idea behind RAII is:
Treat resource acquisition as though you are initializing an object.
Make sure the acquired resource(s) is(are) released when the object is destructed.
You can read more on RAII at Wikepedia.
So, what are the following people talking about?
What is RAII?
RAII in a nutshell is a very simple idea. It is the idea that no object may exist at all unless it is fully initialised.
Why is that good?
We now have a concrete guarantee that a 'half built' object cannot be accidentally used - because at no point in the logical flow of the program can it possibly exist.
How do we achieve it?
a) always manage resources (memory, files, mutex locks, database connections) in a class of their own which is specifically tailored to only managing that resource.
b) build complex logic out of collections of objects covered by [a]
c) Always throw if anything in the constructor fails (to guarantee that a failed object cannot exist)
d) if we are managing more than one resource in a class, we ensure that a failed construction cleans up the parts that have already been constructed (NOTE: this is hard [sometimes impossible], and why at this point you should be referred back to [a])
Sounds hard?
Initialising your objects completely in the initialiser list, while wrapping all external resources in a manager class (e.g. files, memory) achieves perfect RAII effortlessly.
What's the advantage?
Your program may now contain only logic which makes it easier to reason about and to read. The compiler will take care of all resource management perfectly.
Effortless Compound Resource Management
An example of RAII that's hard without manager classes and easy with them?
struct double_buffer
{
double_buffer()
: buffer1(std::nullptr) // NOTE: redundant zero construction
, buffer2(std::nullptr)
{
buffer1 = new char[100]; // new can throw!
try {
buffer2 = new char[100]; // if this throws we have to clean up buffer1
}
catch(...) {
delete buffer1; // clean up buffer1
throw; // rethrow because failed construction must throw!
}
}
// IMPORTANT!
// you MUST write or delete copy constructors, move constructor,
// plus also maybe move-assignment or move-constructor
// and you MUST write a destructor!
char* buffer1;
char* buffer2;
};
now the RAII version:
struct double_buffer
{
double_buffer()
: buffer1(new char[100]) // memory immediately transferred to manager
, buffer2(new char[100]) // if this throws, compiler will handle the
// correct cleanup of buffer1
{
// nothing to do here
}
// no need to write copy constructors, move constructor,
// move-assignment or move-constructor
// no need to write destructor
std::unique_ptr<char[]> buffer1;
std::unique_ptr<char[]> buffer2;
};
How does it improve my code?
some safe code that uses RAII:
auto t = merge(Something(), SomethingElse()); // pretty clear eh?
t.performAction();
the same code that does not use RAII:
TargetType t; // at this point uninitialised.
Something a;
if(a.construct()) {
SomethingElse b;
if (b.construct()) {
bool ok = merge_onto(t, a, b); // t maybe initialised here
b.destruct();
a.destruct();
if (!ok)
throw std::runtime_error("merge failed");
}
else {
a.destruct();
throw std::runtime_error("failed to create b");
}
}
else {
throw std::runtime_error("failed to create a");
}
// ... finally, we may now use t because we can (just about) prove that it's valid
t.performAction();
The difference
The RAII code is written solely in terms of logic.
The non-RAII code is 40% error handling and 40% lifetime management and only 20% logic. Furthermore, the logic is hidden in amongst all the other garbage, making even these 11 lines of code very hard to reason about.

Leaking in constructor

Do I leak if I allocate memory with new in the constructor of an object and immediately after I throw an exception?
The object shouldn't be constructed at all and thus no destructor will be called, but what about that memory?
e.g.
MyObject() {
data = new char[200]; // Will this be leaked?
if(something_is_wrong)
throw exception();
}
It will leak. Once you have gotten a pointer from new it eventually needs to be deleted. The solution is to make data a smart pointer (or in this case, probably a std::string); while MyObject's destructor won't be called, data members' destructors are called.
Yes, it will be a leak unless data is kind of handle, smart pointer and not a raw pointer char* data. A safe variant of this is:
class MyObject {
std::vector<char> data; // or some handle/smart pointer (i.e. unique_ptr)
// it might be just std::string
public:
MyObject( int sz) : data( sz) {}
};
In this case the memory used is now managed by vector. You can of course do it by yourself what is actually done in vector already and is exception safe. This is you can use approach similar to std::uninitialized_fill.
Unless data is a smart pointer (or, more generally, any object that frees the memory passed to it when it destructs) you will leak memory.
The new will need to be balanced with a delete[] (note the []). It's important to note that, since a MyObject instance was not created, the destructor to MyObject will not be called so you cannot rely on any memory cleanup there.
Two alternatives.
free the memory before the throw statement.
Make data a smart pointer (if it isn't already).
2 is preferred - by exploiting RAII it makes code more stable.
The situation that you sketch,
MyObject() {
data = new char[200]; // Will this be leaked?
if(something_is_wrong)
throw exception();
}
will1 leak unless automatic garbage collection is used (and even so it may still leak).
This case is very easily dealt with by using an appropriate standard library container:
MyObject()
{
string data( 200, '\0' );
if(something_is_wrong)
throw exception();
}
And in general preferentially use standard library containers instead of all this new'ing, and if there isn't a suitable container, use smart pointers such as std::unique_ptr.
In short, there's not really a problem, not any more than a call to std::terminate is a problem (just remove the call, or don't do it in the first place).
However, if you define a custom allocation function for the class, and forget to define a corresponding deallocation function, then throwing an exception from a constructor can leak memory.
As a learner simply don't define allocation functions.
As a professional remember to do it properly if at some time you should really need it.
1) Under the reasonable assumption that you're not using a smart pointer to guarantee cleanup and asking this question without mentioning the smart pointer.

Whether following code is prone to memory leak?

I am new to C++ and I want to know whether following code is prone to memory leak.
Here I am using a std::ostream pointer to redirect output to either console or to a file.
For this I am calling new operator for std::ofstream.
#include <iostream>
#include <fstream>
int main() {
bool bDump;
std::cout << "bDump bool" << std::endl;
std::cin >> bDump;
std::ostream *osPtr;
if (bDump) {
osPtr = new std::ofstream("dump.txt");
} else {
osPtr = &std::cout;
}
*osPtr << "hello";
return 0;
}
And one more thing, I have not closed the file which I opened while calling constructor for ofstream. Do we have any potential data loss situation here. as file is not closed.
Yes. Definitely. Any time you call new without delete, there's a memory leak.
After your code has executed, you need to add this:
if(bDump)
{
delete osPtr;
}
As #Mahmoud Al-Qudsi mentioned anything you new must also be deleted otherwise it will be leaked.
In most situation you do not want to use delete but rather you want to use a smart pointer to auto-delete the object. This is because in situations with exceptions you could again leak memory (while RAII) the smart pointer will guarantee that the object is deleted and thus the destructor is called.
It is important the at the destructor is called (especially in this case). If you do not call the destructor there is a potential that the not everything in the stream will be flushed to the underlying file.
#include <iostream>
#include <fstream>
int doStuff()
{
try
{
bool bDump;
std::cout<<"bDump bool"<<std::endl;
std::cin>>bDump;
// Smart pointer to store any dynamic object.
std::auto_ptr<std::ofstream> osPtr;
if(bDump)
{
// If needed create a file stream
osPtr.reset(new std::ofstream("dump.txt"));
}
// Create a reference to the correct stream.
std::ostream& log = bDump ? *osPtr : std::cout;
log << "hello";
}
catch(...) {throw;}
} // Smart pointer will correctly delete the fstream if it exists.
// This makes sure the destructor is called.
// This is guaranteed even if exceptions are used.
Yes, anything that is newed but never deleteed leaks.
In some cases, it is perfectly reasonable to allocate left right and center, and then just exit, particularly for short-lived batch-style programs, but as a general rule you should delete everything you new and delete[] everything you new[].
Especially in the case above, leaking the object is unsafe, since the object being leaked is an ostream that will never write unflushed content.
There is no leak in the code shown. At all times during the execution, all allocated objects are referenceable. There is only a memory leak if an object has been allocated and cannot be referenced in any way.
If the pointer goes out of scope, or its value is changed, without the object being deallocated, that is a memory leak. But so long as the pointer is in the outermost scope and nothing else changes its value, there is no leak.
"In object-oriented programming, a memory leak happens when an object is stored in memory but cannot be accessed by the running code." Wikipedia -- 'Memory leak'
The other answers suggest that any program that uses typical singleton patterns or doesn't free all allocated objects prior to termination has a memory leak. This is, IMO, quite silly. In any event, if you accept that definition, almost every real world program or library has a memory leak, and memory leaks are certainly not all bad.
In a sense, this kind of coding is prone to a memory leak, because it's easy to change the value of the pointer or let it go out of scope. In that case, there is an actual leak. But as shown, there is no leak.
You may have a different problem though: If the destructor has side-effects, not calling it can result in incorrect operation. For example, if you never call the destructor on a buffered output stream writing to a file, the last writes may never actually happen because the buffer didn't get flushed to the file.