I'm working on a project for class and I'm using classes and pointers of type class to call some functions in the class but it's crashing on Code Blocks and Eclipse and I don't know what is going on
Note it crashes when assigning x with y
#include <iostream>
using namespace std;
class a{
private:
int x;
public:
void set_X(int y){
x=y;
}
};
int main()
{
a *Ptr;
Ptr->set_X(5);
}
a *Ptr;
Ptr->set_X(5);
Your Ptr does not point to anything. Trying to invoke a member function on an uninitialised pointer results in undefined behaviour. Crashing is just one of the many more or less random things that can happen.
Luckily, in your example, you do not need a pointer anyway. You can simply write:
a my_a;
my_a.set_X(5);
Pointers often point to dynamically allocated objects. If this is what you want, you must use new and delete accordingly:
a *Ptr = new a;
Ptr->set_X(5);
delete Ptr;
In modern C++, std::unique_ptr is typically a superior alternative because you don't have to manually release the allocated memory, which removes a lot of potential programming errors:
auto Ptr = std::make_unique<a>();
Ptr->set_X(5);
// no delete necessary
Basic rule: creating a pointer (a variable that contains the address of an object, or otherwise is NULL (or nullptr since 2011)) as pointed out by Christian Hackl in comments) does not create a corresponding pointee (an object who's address can be stored in the pointer).
More formally, Ptr is an uninitialised pointer. Even accessing its value gives undefined behaviour (e.g. some_other_pointer = Ptr). For operator -> to work correctly, the pointer must first be initialised so it points at a valid object.
a aobj;
a *Ptr = &aobj;
Ptr->set_X(42); // OK
a *Ptr2 = new a;
Ptr2->set_X(42); // OK
delete Ptr2;
You have just declared a pointer variable of type a* but it doesn't point to a valid memory address. And since you are calling a member function via that pointer which updates a data-member hence you have segfault because this pointer is NULL.
You must initialize pointer with some valid memory address of class a object.
Following can be done,
a* ptr = new a;
ptr->set_X(5);
// ...
delete ptr;
In this case. It would be better that you should use some smart_ptr like std::shared_ptr or std::unique_ptr so that you don't need to worry about releasing resources manually.
Or
a* ptr;
a aobj_;
ptr = &aobj_;
ptr->set_X(5);
Related
I want to create a class that contains a pointer, and upon initialization, the pointer can be dereferenced to give an integer assigned at initialisation.
This was my first attempt to write this code. This passed compiler and gave me the correct result without warning. However I later think this code has a potential problem.
That is in the constructor, the integer a is created on a stack framed to the constructor function. I am however making 'ptr' pointing to this stack memory address. The problem is this memory can be reused upon maybe calling other functions, so I might get garbage value if I am not lucky.
#include <iostream>
using namespace std;
class P {
public:
int *ptr;
P(int);
};
P::P(int a){
int *ptr = new int (0);
ptr = &a;
}
int main() {
P p(99);
cout <<*(p.ptr) <<endl;
}
A better way would be to create an integer variable on heap, copy the value of a to that variable, and make ptr pointing to that memory space on heap.
P::P(int a){
int *i = new int (0);
*i = a;
ptr = i;
}
Is my analysis correct?
Thanks!
The statements
int *ptr = new int (0);
ptr = &a;
are problematic, but probably not because of the reasons you think.
The reason it's problematic is because you define a new and distinct local variable ptr inside the function. This is not the same as the P::ptr member variable.
There's also a second problem, which is a memory leak. You allocate memory with new, but you never free the memory with delete.
If you really is required to use a raw and non-owning pointer to a single int value, I recommend you do it using a constructor initializer list:
P(int a)
: ptr{ new int(a) }
{
// Empty
}
Here new int(a) will create a new int value and copy the value of a into it.
Remember to then create a destructor which free's the memory you have allocated. And then you need to learn about the rules of three, five and zero.
To use the rule of zero, and to avoid memory leaks and make life simpler, use a smart pointer like std::unique_ptr:
struct P
{
std::unique_ptr<int> ptr;
P(int a)
: ptr{ std::make_unique<int>(a) }
{
}
};
And of course, since it's just about a single int value, and you don't need a reference to the original value, there's no need for pointers at all.
If I don't use delete ptr at comment here in below code, then it causes a memory leak?
int *create(){
int a;
int *a_ptr{&a};
return a_ptr;
}
int main(){
int *ptr = {nullptr};
ptr = create();
//here
return 0;
}
Actually you return pointer to object that is destroyed after create function ends its execution.
int a; is created on stack so a_ptr points to some place on stack. During return all objects on stack are destroyed and there is only a_ptr left there as value.
No, you don't have memory leak but ptr in main() function is invalid as points to non-existing object.
In main() scope you initialized a pointer to nullptr without allocating any space (You have not used the new keyword).
In create() function you declared an int without initializing it (it could have any value), then you declared a a_ptr pointing to the reference of a.
When the code exits from the create() function scope, the variable a is out of scope and those memory cells will be marked as unused. So, when the returned pointer it's assigned to the ptr in main() scope it will points to unused memory and this will lead to undefined behaviour whenever you use this pointer.
Essentialy, the pointer is already pointing to nullptr and you don't have to delete it, because you haven't allocated any space for the pointer and you have nothing to delete.
No, you must only delete pointers that were created by new. Never delete pointers to local variables. However, your code has undefined behaviour and that should be your primary concern.
When create() returns, the lifetime of it's local variable a will end and any pointers/references to it will become invalid. Accessing such an invalid pointer causes undefined behaviour which often manifests as segmentation fault. Never return pointers or references to local variables from a function.
One option is to actually new the pointer you return:
int *create(){
return new int{0};
}
int main(){
int *ptr = create();
delete ptr;
}
I wouldn't recommend this however. In modern C++ you can and should avoid new/delete/new[]/delete[] and prefer smart pointers or vectors as appropriate.
If I don't use delete ptr at comment here in below code, then it causes a memory leak?
No. Variables with automatic storage duration are destroyed automatically when they go out of scope. There is no memory leak in the example.
However if you do delete the ptr then the behaviour of the program will be undefined. That's because you may delete only what you've allocated with new.
Even if you only indirect through the pointer, will the program be undefined. The returned pointer is always invalid and nothing useful can be done with it.
I'm a bit curious about a pointer's behaviour in C++. So I have this little program to test out and unfortunately it run well.
#include <iostream>
class Test{
public:
Test(){
std::cout<<"Test Created!\n";
}
~Test(){
std::cout<<"Test Destroyed!\n";
}
};
void destroyer(Test* T){
Test* temp = T;
delete temp;
}
int main(){
Test* ptr = new Test();
destroyer(ptr);
}
And it gives in return
Test Created!
Test Destroyed!
And I draw the conclusion that when we delete a pointer, actually it just deletes the object that the pointer refers to, not the variable itself (variable pointer will automatically deleted at the end of program, same as other primitive data type). Is my thought about this true?
Yes, the delete operator only calls the destructor and frees the memory occupied by the object that the pointer points to. The pointer itself is a local variable like any other and cannot be (and does not need to be) deleted.
It may be worth noting that calling delete ptr; does not change the value of ptr, so after deleting the pointer ptr would point to memory that has been deallocated. It would be undefined behaviour to access that memory after deleting it.
delete is an operator that looks at the object pointed to by the pointer object. The pointer variable is still a local value whose lifetime is tied to the scope it is declared in.
You have 3 pointer objects, with differing lifetimes. Only ptr in main lasts to the end of the program. T and temp only exist during destroyer.
Colloquially we say "delete the pointer" when we write
delete x;
However, this isnt quite accurate. What is deleted is the object pointed to by x.
And i have conclusion that when we delete pointer, actually it just delete the object that pointer refer to not the variable itself (variable pointer will automatically deleted at the end of program, same as other primitive data type). Is my thought about this true?
Yes.
In practice the inaccuracy mentioned above is just fine because after deleting the object the pointer value cannot be used without invoking either implementation defined or undefined behavior and that also affects other pointers to the same object:
int* x = new int(42);
int* y = x;
detele x;
std::cout << x << y; // implementation defined
std::cout << *x << *y; // undefined
x = new int(42); // OK
For details see here.
Assume a pointer object is being allocated on one point and it is being returned to different nested functions. At one point, I want to de-allocate this pointer after checking whether it is valid or already de-allocated by someone.
Is there any guarantee that any of these will work?
if(ptr != NULL)
delete ptr;
OR
if(ptr)
delete ptr;
This code does not work. It always gives Segmentation Fault
#include <iostream>
class A
{
public:
int x;
A(int a){ x=a;}
~A()
{
if(this || this != NULL)
delete this;
}
};
int main()
{
A *a = new A(3);
delete a;
a=NULL;
}
EDIT
Whenever we talk about pointers, people start asking, why not use Smart Pointers.
Just because smart pointers are there, everyone cannot use it.
We may be working on systems which use old style pointers. We cannot convert all of them to smart pointers, one fine day.
if(ptr != NULL) delete ptr;
OR
if(ptr) delete ptr;
The two are actually equivalent, and also the same as delete ptr;, because calling delete on a NULL pointer is guaranteed to work (as in, it does nothing).
And they are not guaranteed to work if ptr is a dangling pointer.
Meaning:
int* x = new int;
int* ptr = x;
//ptr and x point to the same location
delete x;
//x is deleted, but ptr still points to the same location
x = NULL;
//even if x is set to NULL, ptr is not changed
if (ptr) //this is true
delete ptr; //this invokes undefined behavior
In your specific code, you get the exception because you call delete this in the destructor, which in turn calls the destructor again. Since this is never NULL, you'll get a STACK OVERFLOW because the destructor will go uncontrollably recursive.
Do not call delete this in the destructor:
5.3.5, Delete: If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will
invoke the destructor (if any) for the object or the elements of the array being deleted.
Therefore, you will have infinite recursion inside the destructor.
Then:
if (p)
delete p;
the check for p being not null (if (x) in C++ means if x != 0) is superfluous. delete does that check already.
This would be valid:
class Foo {
public:
Foo () : p(0) {}
~Foo() { delete p; }
private:
int *p;
// Handcrafting copy assignment for classes that store
// pointers is seriously non-trivial, so forbid copying:
Foo (Foo const&) = delete;
Foo& operator= (Foo const &) = delete;
};
Do not assume any builtin type, like int, float or pointer to something, to be initialized automatically, therefore, do not assume them to be 0 when not explicitly initializing them (only global variables will be zero-initialized):
8.5 Initializers: If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an
object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized
So: Always initialize builtin types!
My question is how should I avoid double delete of a pointer and prevent crash.
Destructors are ought to be entered and left exactly once. Not zero times, not two times, once.
And if you have multiple places that can reach the pointer, but are unsure about when you are allowed to delete, i.e. if you find yourself bookkeeping, use a more trivial algorithm, more trivial rules, or smart-pointers, like std::shared_ptr or std::unique_ptr:
class Foo {
public:
Foo (std::shared_ptr<int> tehInt) : tehInt_(tehInt) {}
private:
std::shared_ptr<int> tehInt_;
};
int main() {
std::shared_ptr<int> tehInt;
Foo foo (tehInt);
}
You cannot assume that the pointer will be set to NULL after someone has deleted it. This is certainly the case with embarcadero C++ Builder XE. It may get set to NULL afterwards but do not use the fact that it is not to allow your code to delete it again.
You ask: "At one point, I want to de-allocate this pointer after checking whether it is valid or already de-allocated by someone."
There is no portable way in C/C++ to check if a >naked pointer< is valid or not. That's it. End of story right there. You can't do it. Again: only if you use a naked, or C-style pointer. There are other kinds of pointers that don't have that issue, so why don't use them instead!
Now the question becomes: why the heck do you insist that you should use naked pointers? Don't use naked pointers, use std::shared_ptr and std::weak_ptr appropriately, and you won't even need to worry about deleting anything. It'll get deleted automatically when the last pointer goes out of scope. Below is an example.
The example code shows that there are two object instances allocated on the heap: an integer, and a Holder. As test() returns, the returned std::auto_ptr<Holder> is not used by the caller main(). Thus the pointer gets destructed, thus deleting the instance of the Holder class. As the instance is destructed, it destructs the pointer to the instance of the integer -- the second of the two pointers that point at that integer. Then myInt gets destructed as well, and thus the last pointer alive to the integer is destroyed, and the memory is freed. Automagically and without worries.
class Holder {
std::auto_ptr<int> data;
public:
Holder(const std::auto_ptr<int> & d) : data(d) {}
}
std::auto_ptr<Holder> test() {
std::auto_ptr<int> myInt = new int;
std::auto_ptr<Holder> myHolder = new Holder(myInt);
return myHolder;
}
int main(int, char**) {
test(); // notice we don't do any deallocations!
}
Simply don't use naked pointers in C++, there's no good reason for it. It only lets you shoot yourself in the foot. Multiple times. With abandon ;)
The rough guidelines for smart pointers go as follows:
std::auto_ptr -- use when the scope is the sole owner of an object, and the lifetime of the object ends when the scope dies. Thus, if auto_ptr is a class member, it must make sense that the pointed-to object gets deletes when the instance of the class gets destroyed. Same goes for using it as an automatic variable in a function. In all other cases, don't use it.
std::shared_ptr -- its use implies ownership, potentially shared among multiple pointers. The pointed-to object's lifetime ends when the last pointer to it gets destroyed. Makes managing lifetime of objects quite trivial, but beware of circular references. If Class1 owns an instance of Class2, and that very same instance of Class2 owns the former instance of Class1, then the pointers themselves won't ever delete the classes.
std::weak_ptr -- its use implies non-ownership. It cannot be used directly, but has to be converted back to a shared_ptr before use. A weak_ptr will not prevent an object from being destroyed, so it doesn't present circular reference issues. It is otherwise safe in that you can't use it if it's dangling. It will assert or present you with a null pointer, causing an immediate segfault. Using dangling pointers is way worse, because they often appear to work.
That's in fact the main benefit of weak_ptr: with a naked C-style pointer, you'll never know if someone has deleted the object or not. A weak_ptr knows when the last shared_ptr went out of scope, and it will prevent you from using the object. You can even ask it whether it's still valid: the expired() method returns true if the object was deleted.
You should never use delete this. For two reasons, the destructor is in the process of deleting the memory and is giving you the opportunity to tidy up (release OS resources, do a delete any pointers in the object that the object has created). Secondly, the object may be on the stack.
in the following code:
class x
{
private:
someRef& m_ref;
public:
x(someRef& someRef):m_ref(someRef)
{
}
do I need to do:
~x()
{
delete m_ref;
}
which by the way doesnt work without getting the pointer...
basically I'm asking: Do I need to call a destructor on a reference member?
No.
You only need to delete an object if you own it. If you were passed a reference, it means that someone else owns it, thus it's unnecessary and thankfully the language prevents it.
I don't think one actually strictly speaking ever deletes even pointers. What you delete are dynamically allocated objects (or arrays of objects) that the pointer is a handle for. If the object originates from a call to new and it is the responsibility of this class to clean up after this object, then you call delete.
It is technically possible that a reference might be referring to a dynamically allocated object:
int main()
{
//in principle a reference can also refer to a dynamically allocated object
x var(*new someRef);
}
//and if that is the intended usage:
x::~x()
{
delete &m_ref;
}
However, this would be incredibly bad style. By convention, the "owning" handle of a dynamically allocated object should not be a reference.
No. You can only delete pointers, not references, and even then you must only delete objects that you allocated using the new operator. And then you must be sure to delete them only once. Here is the case in which you would need to use delete in your destructor:
class x
{
private:
someObj* m_ptr;
public:
x():m_ptr(new someObj())
{
}
~x()
{
delete m_ptr;
}
But in general it's best to avoid even this and use smart pointers instead.
I want to clarify some misconceptions you seem to have that are beyond the intent of your question:
When a class's destructor is called all of it's members' destructors get called as well.
Calling delete is not the same as calling the destructor. delete explicitly calls the destructor and also calls operator delete at the objects location, it is a 2 part thing.
For a small bit of extra clarification I want to offer the following:
int *pi = new int;
//int& ir = pi; // can't do
// this a reference to the pointer but it is an error
// because or the type difference int& vs int* and
// static_cast won't help. reinterpret_cast would allow
// the assignment to take place but not help the 'delete ir'
int& ir = *pi; // this is OK - a reference to what the pointer points to.
// In other words, the the address of the int on the heap.
//delete ir; // can't do, it is a reference and you can't delete non-pointers.
delete &ir; // this works but it is still not "deleting a reference".
// The reference 'ir' is another name for the heap-based int.
// So, &ir is the address of that int, essentially a pointer.
// It is a pointer that is being used by delete, not a reference.