This question already has answers here:
Accessing class members on a NULL pointer
(8 answers)
Closed 10 months ago.
#include <iostream>
class TestClass {
public:
TestClass() {
std::cout << "TestClass instantiated\n";
}
~TestClass() {
std::cout << "TestClass destructed\n";
}
void PrintSomething() {
std::cout << "TestClass is printing something\n";
}
};
int main() {
TestClass* tClass = new TestClass();
delete tClass;
tClass = nullptr;
tClass->PrintSomething();
std::cout << "Exiting...\n";
return 0;
}
Result:
TestClass instantiated
TestClass destructed
TestClass is printing something
Exiting...
I thought that trying to print something after the tClass pointer had been set to nullptr would cause a nullpointer exception error, but it prints just fine.
Why doesn't accessing this nullpointer cause an exception?
Because it's not specified to cause an exception. Accessing through a null poitner results in undefined behaviour. Don't do it.
Related
This question already has answers here:
What does '&' do in a C++ declaration?
(7 answers)
how does the ampersand(&) sign work in c++? [duplicate]
(3 answers)
Closed 1 year ago.
In the following lines of code, if I remove the '&' from the line ('***'), there would not be any change in the functionality apparently. Is there any reason to keep it as is or could it be useful in any case?
Would you elaborate a little bit about the differences?
Thanks.
#include <iostream>
class Entity
{
public:
void Print() const
{
std::cout << "Hello" << std::endl;
}
Entity()
{
std::cout << "Constructed!" << std::endl;
}
};
int main()
{
Entity e;
Entity* ptr = &e;
// ***
Entity& entity = *ptr;
entity.Print();
std::cin.get();
}
You can see the difference if you actually put some state into your class and try to change it. If you copy by reference the change in the original is also seen in the copy. If you copy by value (without the & ) then a change in the original is not seen in the copy.
#include <iostream>
#include <string>
class Entity
{
public:
std::string m_message;
Entity(std::string msg ):m_message(msg){}
void Print() const
{
std::cout << m_message << std::endl;
}
};
int main()
{
Entity e("cat");
Entity* ptr = &e;
// assign by reference is a bit like taking a pointer in
// that it refers back to the original object but you
// don't have to use '*' to dereference it. Also it is
// not able to be null.
Entity& byRef = *ptr;
// assign by value creates a new object with no link to
// the previous object
Entity byVal = *ptr;
byRef.Print();
byVal.Print();
std::cout << "========" << std::endl;
e.m_message="dog";
byRef.Print();
byVal.Print();
}
which outputs
cat
cat
========
dog
cat
See https://godbolt.org/z/r4qehWxY3
This question already has answers here:
What will happen when I call a member function on a NULL object pointer? [duplicate]
(6 answers)
Closed 3 years ago.
I was going through shared_ptr and came across this.
class A
{
public:
A() { cout << "In constructor" << endl; }
~A() { cout << "Destructor" << endl; }
void fun() { cout << "In fun... " << endl; }
};
int main()
{
shared_ptr<A> a;
a->fun();
return 0;
}
The output of this is - In fun...
I would like to understand how is this giving above output.
On further experimentation if there is a member variable and being used in this function it throws an SIGSEGV.
class A
{
public:
A() { cout << "In constructor" << endl; }
~A() { cout << "Destructor" << endl; }
void fun() { a = 5 ; cout << "In fun... " << endl; }
int a;
};
int main()
{
// A::fun();
shared_ptr<A> a;
a->fun();
return 0;
}
Above throws SIGSEGV stating this pointer is null.
The code in both cases has undefined behavior because the raw pointer of the shared_ptr pointer is initialized by nullptr.
In the second case the code tried to access memory of the data member a using nullptr.
In the first case the code executed without a failure only due to there is no access to the memory of the object. However the code has undefined behavior because you may not use a null-pointer to access non-static members of a class..
This question already has answers here:
c++ delete pointer issue, can still access data [closed]
(6 answers)
Closed 3 years ago.
I tried deleting this pointer from constructor, and afterwards when i access private variable through a member function, the variable is fetched correctly.
If I try to delete this again(in constructor or func()), my program crashes. That means this pointer is deleted fine in constructor.
class B
{
int a;
public:
B()
{
std::cout << this;
std::cout << "\nConstructor\n";
delete this;
a = 5;
std::cout << "\n" << this;
}
~B()
{
std::cout << "Destructor\n";
}
void func()
{
std::cout << "\n" << a << " Func\n";
}
};
int main(int argc, char* argv[])
{
B *b = new B();
b->func();
return 0;
}
But calling func() prints correct output. I expected some error due to deleted this. Why the implicit argument of func() is not updated when deleted?
delete this is allowed and just fine. Accessing any members of the class after deleting it however is not allowed and is undefined behavior. Your code appearing to work is one form that UB can take.
This question already has answers here:
std::enable_shared_from_this: is it allowed to call shared_from_this() in destructor?
(4 answers)
Closed 6 years ago.
Somehow after p->start() is called - shared_from_this throws bad_weak_ptr.
But as you can see p->start() called after shared_ptr is fully initiated.
struct A : std::enable_shared_from_this<A>
{
std::thread* t = nullptr;
A() {}
~A(){
t->join();
delete t;
}
void f() {
try{
auto p = this->shared_from_this();
std::cout << "p:" << p.get() << "\n";
} catch(...) {
std::cout << "Exception !!!\n";
}
}
void start() {
t = new std::thread(&A::f,this);
}
};
std::shared_ptr<A> create() {
A* a = new A();
std::shared_ptr<A> p(a);
p->start();
return p;
}
int main()
{
int i = 0;
std::map<int,std::shared_ptr<A>> map;
while( i < 1024) {
auto ptr = create();
map[i++] = ptr;
}
return 0;
}
link to working code (coliru) - unexplained bad_weak_ptr - exception is thrown ...
Your problem is that you have a race condition on the join. main may be exiting, destroying your objects in the map. The shared_ptr in the map is destroyed, calling your object's destructor which wants to join, but it's too late: the shared_ptr that enable_shared_from_this wants to use is toast. Then (race condition) in the object's own thread it tries to get a shared from this on a dead weak_ptr, which causes the exception to be thrown and message printed on cout.
This question already has answers here:
What happens when you deallocate a pointer twice or more in C++?
(8 answers)
Closed 8 years ago.
In the following program, how is p getting deleting twice, as it is pointing to same memory location?
#include <iostream>
using namespace std;
class Test {
public:
int *p;
Test() {
cout << "Constructor is executed\n";
}
~Test() {
cout << "Destructor is executed\n";
delete[] p;
cout << "p deleted\n";
}
void make() {
p = new int[5];
}
//here destructor is called expllicitly
void show() {
this->Test::~Test();
}
};
int main() {
Test t;
t.make();
t.show();
return 0;
}
Output:
Constructor is executed
Destructor is executed
p deleted
Destructor is executed
p deleted
You are calling the destuctor once yourself (Case 1) then the destructor is getting called on the object when it is no longer in scope (Case 2).
1) Show() calls the destructor
t.show();
2) t falls out of scope at the end of main, therefore calling the destructor.
int main()
{
Test t;
t.make();
t.show();
return 0;
} // t will now call its destructor
/*
p is deleted twice becasue the destructor, Test::~Test() is called twice.
it is called once explicitly in show() , and once implicitly when main() returns.
*/
#include <iostream>
using namespace std;
class Test
{
public:
int *p;
Test() { cout << "Constructor is executed\n"; }
~Test()
{
cout << "Destructor is executed\n";
delete []p;
cout<<"p deleted\n";
}
void make(){ p = new int[5];}
/**here destructor is called expllicitly**/
void show() { this->Test::~Test(); }
};
int main()
{
// Right here you create an object of type Test, which is destroyed when the function returns.
Test t;
t.make();
t.show();
return 0; // Right here is the second implicit call of the destructor, Test::~Test() .
}