I have a C++ code mentioned below:
#include<iostream>
#include<stdexcept>
const long MAX = 10240000;
class Widget{
public:
Widget(){
ok = new int [1024];
prob = new int [100*MAX];
}
~Widget(){
std::cout<<"\nDtoR of Widget is called\n";
delete ok; ok = NULL;
delete prob; prob = NULL;
}
//keeping below public: Intentionally
int* ok;
int* prob;
};
void func(){
Widget* pw = NULL; // <<<<--------------- Issue in Here
try{
pw = new Widget;
}
catch(...){
delete pw;
std::cout<<"\nIn catch BLOCK\n";
if(pw->ok == NULL){
std::cout<<"\n OK is NULL\n";
}
throw;
}
delete pw;
}
int main(){
try{
func();
}
catch(std::bad_alloc&){
std::cout<<"\nError allocating memory."<<std::endl;
}
std::cout<<std::endl;
system("pause");
return 0;
}
Now in function func(), i am seeing two different behavior depending on if i do not set pointer 'pw' to NULL and if i do set 'pw' pointer to NULL (like code above). I was under the impression that it is 'good' practise to first set pointer to NULL and then initialize it. But when i initilize it to NULL then the output just shows "In catch BLOCK" and later app crashes. but if i do not set pw pointer to NULL, then i see destructor of pw is called and following output is shown w/o any app crash.
DtoR of Widget is called
In catch BLOCK
OK is NULL
Error allocating memory.
Press any key to continue . . .
My question is why such difference in one case when we are not initializing 'pw' pointer to NULL and in other case we are setting it to NULL. Why destructor is called in one case and why it was not called in another.
Note: The intent of this code is to throw bad_alloc exeption.
If you do not set pw to NULL then you will leave it uninitialized. Then, when new operator inside a "try" block throws an exception, it never returns, and you get into catch block. Since new never returned, pw will still be not initialized, and you will pass a random address to delete. That gives you an undefined behavior.
In your catch block, you have:
if(pw->ok == NULL)
At this point, pw is NULL (or garbage, in the case that you didn't initialise it). pw-ok attempts to dereference it, giving undefined behaviour (a crash in this case).
If you didn't initialise it, then the delete pw will crash before printing the "catch" message; most likely, it will print the "Dtor" message before crashing, but there is no guarantee since you're firmly in the realm of undefined behaviour.
If you did initialise it, then delete pw is unnecessary but harmless; deleting a null pointer is defined to do nothing. So in that case you won't crash until you dereference it.
In any event, you have an unfixable memory leak - the first allocation ok = new int[1024] will have succeeded, but you have lost the only pointer to it. This is why you should always manage dynamic memory using smart pointers, containers, and other RAII techniques.
you are going to intend the bad_alloc exeption.but you have more unhandled exceptions!
It is not ok to delete pw first and then using the pointer of it!
delete pw;
if(pw->ok == NULL)
Why would you call pw->ok after you delete pw? It's already gone.
You constructor should have member initializes
Widget():ok(NULL), prob(NULL) {
...
}
because if Widget() fails, you don't know which member variable is initialized and which is not which can cause problem in your destructor.
Since you allocated with int[], you need to delete[] not just delete in your destructor.
You are seeing the app crash when you set pw to NULL because of the line
if (pw->ok == NULL)
You are dereferencing NULL which is causing the crash. In the other case you are deleting garbage which will give you undefined behavior.
Also, you should not use a pointer after calling delete on it. That can cause all kinds of weird behavior.
To explain more of what is happening. Your Widget constructor is throwing the allocation exception. In this case most likely the allocation for ok completed, but the allocation for prob failed. Your constructor never finishes, leaking the memory that was allocated to the ok variable. If you want to ensure the memory is cleaned up, you should add a try catch in your constructor.
Widget() : ok(NULL), prob(NULL)
{
try
{
ok = new int [1024];
prob = new int [100*MAX];
}
catch(...)
{
std::cout << "\nCtor of Widget threw exception\n";
delete [] ok;
delete [] prob;
throw;
}
}
It's good to initialize pw to NULL, but when deleting it, you should first check if pw is not null. Something like:
if (pw) delete pw;
Also, if pw is NULL, you can't reference its members.
Related
The code below works fine, but if I try to access the private member variable m_sal in the function fun(), it leads to segmentation fault.
Can any one explain what's the reason ?
class Emp
{
int m_sal;
public :
void fun(char* name)
{
std::cout<<"Name :"<<name<<std::endl;
}
};
int main()
{
Emp *e = NULL;
e->fun("Hi");
return 0;
}
Calling a method by a NULL pointer - as you are doing - is undefined behaviour. So it may crash, not crash, do anything.
First might want to change your method's signature to read
void fun (const char* name) const;
Converting from "Hi" to char * is deprecated and const correctness highly recommended. Your crash is caused as people mentioned by calling your method on a null pointer. Try
Emp * e = new Emp;
e->fun("Hi");
instead.
Of course it crashes.
Emp *e = NULL;
creates a pointer which happens to be a null pointer (because of = NULL , but I am sure many of us would prefer = nullptr), so there is no memory allocated for the object it is pointing to. You need to create an object this pointer will point to:
Emp* e = new Emp;
and now you can use it.
The exact reason for the crash is that the application is trying to fetch a value from a very low memory address (pointer's value is 0, for some cases add a few padding bytes maybe for the correct memory layout of the C++ object, but highly possible in this case it just wants to read the memory at address 0) which in most cases and OS's is reserved to be used by the system.
In your code, e is a pointer, not an actual instance of an object. You can either have:
Emp e;
e.fun("Hi");
//No need to clean up stack variable
OR
Emp *e = new Emp;
e->fun("Hi");
delete e; //don't forget to clean up!
What you have is undefined behavior because of using a null pointer to call a function.
I'm always reading that I should not to throw a std::string or some other classes allocating memory. like here or more importantly here on point 3. - Don't embed a std::string object.
So now I'm trying to insert boost::exception to my project and what do I see: lots of strings.
Why doesn't boost comply with its own recommendation?
And if I have parameters which can't be hardcoded, like safed in an config-file, how can I put them into an exception, without using std::string?
Or is the guideline don't use std::string only a do use std::string as seldom as possible guideline? I'm a bit confused...
I've done some research. Please correct me if i'm wrong.
If I understand it right, it's all about the allocation during the throw and what is happening to the allocated memory. So the memory gets lost if I allocate it in the constructor and it can't be freed in the destructor of the exception, that will produce a memory-leak. But it's okay to allocate this before throwing, so the exception is clean.
I tried this:
struct xexception {
int *ttt[10];
xexception() {
ttt[0] = new int[0xfffffffL];
ttt[1] = new int[0xfffffffL];
ttt[2] = new int[0xfffffffL];
ttt[3] = new int[0xfffffffL];
ttt[4] = new int[0xfffffffL];
ttt[5] = new int[0xfffffffL];
ttt[6] = new int[0xfffffffL];
ttt[7] = new int[0xfffffffL];
ttt[8] = new int[0xfffffffL];
ttt[9] = new int[0xfffffffL];
}
~xexception() throw() {
//never happen
delete[] ttt[0];
delete[] ttt[1];
delete[] ttt[2];
delete[] ttt[3];
delete[] ttt[4];
delete[] ttt[5];
delete[] ttt[6];
delete[] ttt[7];
delete[] ttt[8];
delete[] ttt[9];
}
};
int main(int argc, const char *argv[]) {
try {
throw(xexception());
}
catch (const xexception &e) {
std::cerr << "\nttt " << e.ttt[0][0] << std::endl;
}
catch (std::bad_alloc) {
std::cerr << "bad alloc" << std::endl;
}
return 0;
}
The result is, I get the bad_alloc and a huge memory leak.
Now if I do the allocation before, it also throws the bad_alloc but before the exception is created.
My exception to the exception concept is:
Who cares? If I have a bad_alloc in my program, because of a memory_leak or something else (I'm talking about programs on PCs not microcontrollers) I have other problems. Maybe I can figure out that a bad_alloc happened, but where? On my alloc during a function (one of maybe 1000) or in the std::string (well I know it's the string but ... no possibility to manipulate the memory of the string... or its to dissipated).
try {
// where is the error???
int *x = new int[100]; // here?
....
int *y = new int[100]; // or here?
....
int *z = new int[100];
....
int *w = new int[100];
....
int *t = new int[100];
....
int *f = new int[100];
....
std::string str("asdfasdfasdfasdfasdfasdfasdf"); // maybe here
}
catch (the error) {
....
}
And then? Shall I try to figure out where it's happening? Therefore I would use valgrind not exceptions.
void foo() {
int *i = new int[1];
foo();
}
try {
foo();
}
chatch( bad_boy ) {
go_exception_handler_go(parameters); // oh, shit happens: also an stack_overflow may happend, cause stack is also full
}
Or shall i manipulate the errormessage and log it, what definitively would throw the next bad_alloc.
Please don't misunderstand me. Since I've seen the boost::exception I've rewritten my exception class (till waiting on an answer) but I also think it is not really necessary to pick up every grain of sand.
The advice is basically telling you "Don't use any construct that might throw an exception in an exception". That's because if you get an exception while trying to throw an exception, the C++ runtime will just immediately call terminate() and kill your program.
Now if (either) of the exceptions involved would just call terminate() anyways (as is the default for an uncaught exception), then you don't really need to worry about it. For example, if your application can't handle bad_alloc (can't recover from out-of-memory), then you don't need to worry about copy constructors (such as std::string) that might throw it.
But if you want to be able to catch and recover from a bad_alloc, you need to ensure that none of your exception copy constructors can cause one. If you're writing a library that other applications will use, you should not assume that the application does not want to handle bad_alloc.
C++11 make this much easier by using move constructors (instead of copy constructors) where possible. Since the move constructor for std::string never throws exceptions you can safely use a std:string in your exception type as long as you properly implement move constructors, and ensure that they are used. Note that the initial construction of the object to be thrown in a throw expression is NOT part of the exception throwing process, so that constructor can throw an exception without causing a double exception (and terminate()). So if you have:
throw some_function();
some_function might throw an exception (such as bad_alloc) without returning an object to be thrown and that's fine. If it doesn't throw an exception (and returns a valid object), the move constructor for the exception type will be used (if available) for the exception throwing process, and that move constructor must not throw an exception.
Completely independent of the above, whenever you call new you need to ensure that exactly one spot will call delete in every possible case, or you'll leak memory (or crash from a double delete). This becomes tricky any time you have a function that calls new and then does something else that might throw an exception (such as call new again). If this happens in a constructor, the destructor for the object will not be called (though destructors for base classes and fields will be), so you can't do the cleanup in the destructor as you are trying to do with your example.
Fortunately std::unique_ptr exists to make this much easier. If you write your exception class as:
struct xexception {
std::unique_ptr<int[]> ttt[10];
xexception() {
ttt[0].reset(new int[0xfffffffL]);
ttt[1].reset(new int[0xfffffffL]);
ttt[2].reset(new int[0xfffffffL]);
ttt[3].reset(new int[0xfffffffL]);
ttt[4].reset(new int[0xfffffffL]);
ttt[5].reset(new int[0xfffffffL]);
ttt[6].reset(new int[0xfffffffL]);
ttt[7].reset(new int[0xfffffffL]);
ttt[8].reset(new int[0xfffffffL]);
ttt[9].reset(new int[0xfffffffL]);
}
};
it should work and not leak memory.
While I think not using std::string for core, fundamental exceptions may be a good guideline, I don't think user-facing libraries/applications should necessarily follow this.
There may be other reasons, but you hit on the primary one: you'd like to indicate to the user (or developer) contextually meaningful information, which you often cannot do with a mere literal string. A dynamic allocation must occur in order to do this. If, for some reason, you had a bad_alloc, you're probably already hosed to begin with, so it doesn't buy/lose you anything.
Edit:
By the way: the destructor of std::exception is marked as virtual for a reason!
This is regarding deletion of this pointer for an object allocated on heap.Program is as follows,
class Sample{
private:
int m_value1;
int m_value2;
public:
Sample();
void setValues(int m_value1, int m_value2);
void display();
};
Sample::Sample(){
this->m_value1 = 0;
this->m_value2 = 0;
}
void Sample::setValues(int m_value1, int m_value2){
this->m_value1= m_value1;
this->m_value2 = m_value2;
display();
if(this != NULL)
{
cout <<"Deleting this pointer!"<<endl;
delete this;
cout <<"this->m_value1 is "<<this->m_value1<<endl;
cout <<"this->m_value2 is "<<this->m_value2<<endl;
}
}
void Sample::display(){
cout <<"Values are "<<this->m_value1<<" and "<<this->m_value2<<endl;
}
int main(){
Sample *obj1 = new Sample();;
obj1->setValues(4,6);
obj1->display();
getch();
}
OUTPUT:
Values are 4 and 6
Deleting this pointer!
this->m_value1 is 65535
this->m_value2 is 6
Values are 65535 and 6
Why does the value for m_value1 disappear whereas it stays for the other variable m_value2?
Accessing member variables after delete this is undefined behavior - anything can happen, including unexpected data being read, program crashing or anything else. The object has been destroyed and deallocated and you try to dereference an invalid pointer. Once delete this has happened - don't try to access the member variables, don't try t call member functions and don't do anything else (including comparing or casting) to this pointer.
Why does the value for m_value1 disappear whereas it stays for the other variable m_value2?
You are accessing memory after you deleted it. That means you are invoking undefined behavior.
So anything might happen, and your observation is as right or wrong as anything else.
What's likely going on is that the part of memory where m_value1 was stored is reused for something else, whilst the storage for m_value2 has not been used for something else (yet).
It's a matter of chance, probably the operator<< or whatever your do after deleting this allocates enough memory to overwrite the one and not the other.
But when you do something that shouldn't be done you should not rely on any particular consequences.
Dangerous and unpredictable outputs expected including system crash!
Do not delete location pointed to by this directly. its not a good programming practice. and don't use memory after deleting. and even if u have to put it inside an assert()
this != NULL // this will never be NULL if used properly.
I would like to ask if I's correct the following :
MyClass *obj = new MyClass();//allocate memory
obj.Variab="HELLO";
obj=NULL;
delete obj; //free memory
Is the memory allocated for obj deleted after the last two sentences? Appreciate.THX
I would like to mention that I am working in c++ /Ubuntu. G++ is the compiler
EDIT:
What if I have?
int i=0;
list<string>l;
while (i<100)
{
MyClass *obj = new MyClass();//allocate memory
obj->Variab="HELLO";
//add the obj.valie in a list
l.push_back(obj);
i=i+1;
delete obj; //free memory
}
it is ok?
no, you should use delete before assigning to NULL
delete obj; //free memory
obj=NULL;
this is becasue the actual parameter to delete is the address of the allocated memory, but if you assign NULL before delete is used, you are actually passing NULL to delete, and nothing will happen, and you will get yourself a memory leak.
your edit question:
this code will not compile, as obj is not defined outside the while scope, in any case, also, l is a list<string> and you are trying to insert MyClass* types,this will result in another compilation error. also, you should use obj->Variab and not obj.Variab, since obj is a pointer.
EDIT to EDIT:
well, you still got a compilation error, since obj is not defined when you are trying to delete it. try this:
#include <iostream>
#include <list>
using namespace std;
class MyClass {
public:
string Variab;
};
void myfunction (const string& s) {
cout << " " << s;
}
int main()
{
int i=0;
list<string>l;
while (i<100) {
MyClass *obj = new MyClass();//allocate memory
obj->Variab="HELLO";
l.push_back(obj->Variab);
i=i+1;
delete obj; //free memory
}
for_each (l.begin(), l.end(), myfunction);
}
This not correct:
obj = NULL; // don't do that!
delete obj;
When you assign NULL to obj, you're losing the address it contained before, leaking the memory. When you then delete obj, you are deleting NULL, which is well-defined - as doing nothing.
As others have said,
delete obj;
obj = NULL;
is the common pattern to do that.
However, I consider it an anti-pattern.
Whenever you are tempted to assign NULL to a pointer after deleting its content, ask yourself: Why is this pointer still in scope? Are you sure you still need it?
It's much better to simply let a pointer fall out of scope once it's done.
Whenever you are doing
resource r = acquire();
use(r);
free(r);
(with memory/dynamically allocated objects being the most common resource), alarm bells should go off. What if use(r) fails with an exception?
Never use naked, dumb pointers. Better read about RAII and smart pointers.
This would leak, delete will not clean up what you allocated with new. Change the order:
delete obj;
obj = NULL; // I would avoid this.
Setting obj to null does not free the memory you allocated. The memory becomes no longer assigned to a variable but is still reserved, and results in a memory leak. Calling delete on a null pointer will have no effect. After the memory has been freed, the pointer becomes invalid and it is good practice to assign it to null. You need to switch the order of the last 2 statements:
delete obj; //free memory first
obj=NULL; //Set pointer to null for safety
You have to delete the very same address as was returned by new - so you have to first delete, then set to null.
Setting pointer to null doesn't affect allocation - you just overwrite the address stored in the pointer and can't access the object anymore (which implies you can't delete the object and have it leaked).
I am trying a code which Goes like this:-
class test{
int test_int;
public:
virtual int show()
{
return test_int;
}
void set_int(int data){
std::cout<<"received data "<< data <<endl;
test_int = data;
}
};
int main()
{
test *ptr=new test();
ptr=NULL;
ptr->set_int(5);
return 0;
}
Now the problem i am facing is my program after printing the data which i am sending through set_int function got printed but the program crashes just after the completition of the function(set_int).
Am i doing any mistake that is not according to the language standards?
TIA.
Am i doing any mistake that is not according to the language standards?
Yes, you are.
You may not call member functions on a pointer that does not point to a valid object of that type. A null pointer never points to a valid object.
The trivial fix here is to remove the line ptr=NULL;. That way ptr still points to an object when the member function is invoked. This also allows you to fix the memory leak by deleting the pointer later. As a sidenote: avoid manual memory management.
You have pointer to test (test*) set to dynamicaly allocated memory representing instance of that class.
Right after that, you wrote "Nah, I do not need it anymore" and you forget where that newly allocated memory was.
Finally, you are trying to access an object on address 0, which is an invalid operation and will cause runtime error.
You probably meant to do this
int main()
{
test *ptr = new test();
ptr->set_int(5);
// ptr = NULL; // wont free the memory allocated by new
delete ptr; // memory deallocation
ptr = NULL; // now we can safely forget that address (which is now invalid anyways)
return 0;
}