This question already has answers here:
Why am I able to make a function call using an invalid class pointer
(6 answers)
Does calling a method on a NULL pointer which doesn't access any data ever fail?
(3 answers)
When does invoking a member function on a null instance result in undefined behavior?
(2 answers)
Closed 4 days ago.
I ran into a problem with an uninitialised unique ptr, here is the code:
class Demo {
public:
Demo() {}
void noSegFault()
{
std::cout << "noSegFault" << std::endl;
}
void segFault() {
std::cout << "Address of data :" << &data << std::endl;
std::cout << "Before segfault" << std::endl;
data = 234;
std::cout << "After segfault" << std::endl;
}
private:
int data{123};
};
int main() {
std::unique_ptr<Demo> demoPtr{nullptr};
if (demoPtr == nullptr) {
std::cout << "demoPtr is null" << std::endl;
}
demoPtr->noSegFault();
demoPtr->segFault();
return 0;
}
Output:
demoPtr is null
noSegFault
Address of data :0
Before segfault
In this context, demoPtr is initialized with nullptr. I used to believe that accessing nullptr would inevitably lead to a segmentation fault. However, in this program, I can successfully call the noSegFault method and observe its output. Yet, if I attempt to access any variables of the nullptr object(invoking segFault method), a segmentation fault occurs.
So as per the output I can able to invoke the methods which doesn't use its member variables successfully without segmentation fault.Is it the expected behaviour?
godblot link: https://godbolt.org/z/G34c1jefb
Related
This question already has answers here:
What will happen when I call a member function on a NULL object pointer? [duplicate]
(6 answers)
Closed 4 years ago.
I was trying some code. Mistakenly wrote below code (Luckily Now)
Snippet 1
#include<iostream>
using namespace std;
class A {
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
void print() { cout << "A::print()=>" <<this<< endl; }
};
int main() {
A* a = new A;
a->print();
delete a;
a = NULL;
cout << a << endl;
a->print();
return 0;
}
As I know, since I have deleted "a", the program should have crashed (Not so true now). But it did not. Can some please explain the reason behind this. The output image is also attached.
But As soon as I include any member variable in the above program, it crashes.
How ? Why ? Please see Program 2.
Snippet 2
class A {
int val;
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
void print() { cout << "A::print()=>" <<this << val << endl; }
};
int main() {
A* a = new A;
a->print();
delete a;
a = NULL;
cout << a << endl;
a->print();
return 0;
}
The Above program is crashing. Why not the 1st program?
PS: There are chances that it may be the duplicate question. I tried to find the question like this but couldn't find. Though I got this question, I feel it's not the same as I am looking for.
The first one doesn’t dereference any memory pointed by anything, therefore it might not crash. You’re only printing out this which is a pointer value and you’re not dereferencing it. Note that this doesn’t mean it’s ok and will always work! It is definitely not allowed and shouldn’t be done. What happens when this is done is undefined.
Your second example actually tries to use a member variable which means an attempt is made to access memory that isn’t valid. This is also undefined behavior and may cause a crash, or something else. It is undefined.
This question already has answers here:
When does invoking a member function on a null instance result in undefined behavior?
(2 answers)
Closed 4 years ago.
In the following code I create a shared_ptr in the scope and assign it to a weak_ptr. How come when running the code I don't get SEGFAULT, because wp should be invalid out of scope, right?
namespace {
struct Dummy {
int x;
void foo() {
std::cout << "dummy created\n";
}
~Dummy()
{
std::cout << "dummy destroyed\n";
}
};
}
TEST(experimental, ptr_test){
std::weak_ptr<Dummy> wp;
{
auto sp = std::make_shared<Dummy>();
wp = sp;
}
wp.lock()->foo();
};
You're not actually dereferencing anything there though. The lock method will still return a shared_ptr if the locked shared_ptr is null, but that shared_ptr will also be null. In this example, foo doesn't crash on my compiler since it never dereferences the null pointer but it's undefined behavior so you never know what will happen. However, bar will always crash since it needs to dereference the pointer in order to get to x.
The reason why this happens to work is that all member functions compile to normal functions that take a pointer to the object as their first parameter accessible from the function body as this. Calling this function on nullptr will probably work most of the time if nothing in the body of the function dereferences this. You shouldn't do it though, future compiler changes or a port to another architecture could cause this to crash.
#include <iostream>
#include <memory>
struct Dummy {
int x;
Dummy()
: x(10) {
std::cout << "Dummy created" << std::endl;
}
~Dummy() {
std::cout << "Dummy destroyed" << std::endl;
}
void foo() {
std::cout << "foo" << std::endl;
}
void bar() {
std::cout << x << std::endl;
}
};
int main() {
std::weak_ptr<Dummy> wp;
{
auto sp = std::make_shared<Dummy>();
wp = sp;
}
auto locked = wp.lock();
if(locked.get() == nullptr) {
std::cout << "Locked pointer is null" << std::endl;
}
locked->foo(); // Does not crash
((Dummy*)nullptr)->foo(); // Does not crash
locked->bar(); // Will crash
}
Generally, you won't get a segfault unless you actually do something with the invalid memory (and then it won't always segfault - it is up to the hardware to send a signal to the OS, and then up to the OS to actually crash the program). If you were to set x in foo, you may have a better chance of seeing a segfault - but as user2357112 pointed out, the c++ standard does not guarantee a segfault for invalid code.
This question already has answers here:
Calling a function pointer whose assigned function has less arguments then the pointer type
(2 answers)
Closed 7 years ago.
take a look at the following example:
#include <iostream>
#include <string.h>
void Func1(int x)
{
std::cout << "I'm function 1: " << x << std::endl;
}
void Func2(int x, const char* str)
{
std::cout << "I'm function 2: (this is arg1: " << x << " - args2: " << str << ")" << std::endl;
}
uintptr_t GetProcAddress(const char* _str)
{
if (strcmp(_str, "func1") == 0)
{
return reinterpret_cast<uintptr_t>(Func1);
}
else
{
return reinterpret_cast<uintptr_t>(Func2);
}
}
int main()
{
typedef void(*PROCADDR)(int, const char*);
PROCADDR ext_addr = nullptr;
ext_addr = (PROCADDR)GetProcAddress((const char*)"func1");
//call the function
ext_addr(10, "arg");
std::cin.get();
return 0;
}
We are basically calling Func1 with 2 arguments and can switch to call Func2 with the same args and everything works as intended.
Of course the address of both the arguments are always pushed on to the stack even though the second one is never used by the function itself.
Now I understand that the above code should never be used in production-code but my main question is, can the above code cause UB or is the code always expected to act like that?
Best regards
xx
Yes, it's undefined behavior. From [expr.reinterpret.cast]:
A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling
a function through a pointer to a function type (8.3.5) that is not the same as the type used in the definition of the function is undefined.
This question already has answers here:
Vector going out of bounds without giving error
(4 answers)
Closed 8 years ago.
#include <iostream>
#include <vector>
#include <stdexcept>
using namespace std;
class sample
{
public:
sample()
{
cout << "consructor called" << endl;
}
void test()
{
cout << "Test function" << endl;
}
};
int main()
{
vector<sample> v;
sample s;
v.push_back(s);
try
{
v.at(1).test(); // throws out of range exception.
v[1000].test(); // prints test function
}
catch (const out_of_range& oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
return 0;
}
Why v[1000].test(); printing test function on the screen. I have added only one object in the vector. I agree I can access v[1000] becuase its sequential. But why it is giving the exactly correct result? Thanks in advance.
vector::at() explicitly throws out of bound exception while vector::operator is not doing that. By design.
Some std implementations support operator[] bounds checking in debug mode.
As your test() method is not accessing any instance variables and this then it can be executed without problem even this points to non-existent location.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
First of all I'd like to understand why I get lines (5) and (6) in the output and not only one of them.
Second, why mc1.print() prints valid values? Shouldn't _ms point to undefined place after mc1(&MyStruct(mc2)) because the place where MyStruct was created (in cast operator) was already unwind?
struct MyStruct
{
int w;
int h;
MyStruct()
{
cout << "MyStruct" << endl;
}
~MyStruct()
{
cout << "~MyStruct: w=" << w << "h=" << h << endl;;
}
};
class MyClass1
{
public:
MyClass1(MyStruct* ms)
:_ms(ms)
{
cout << "MyClass1" << endl;;
}
~MyClass1()
{
cout << "~MyClass1" << endl;
}
void print()
{
cout << "print: w=" << _ms->w << "h=" << _ms->h << endl;
}
MyStruct* _ms;
};
class MyClass2
{
public:
MyClass2()
{
cout << "MyClass2" << endl;
}
~MyClass2()
{
cout << "~MyClass2" << endl;
}
operator MyStruct()
{
MyStruct ms;
ms.h = 11;
ms.w = 22;;
return ms;
}
};
int main()
{
MyClass2 mc2;
MyClass1 mc1(&MyStruct(mc2));
mc1.print();
return 0;
}
the output is
1. MyClass2
2. MyStruct
3. ~MyStruct: w=22h=11
4. MyClass1
5. ~MyStruct: w=22h=11
6. ~MyStruct: w=22h=11
7. print: w=22h=11
Why there is still valid access to struct after leaving the scope?
There isn't. It isn't valid. You can try to read arbitrary memory addresses, but doing so is not valid". The C++ standard just doesn't say what should happen if you do something "invalid". So your code is allowed to do what you're observing.
First of all I'd like to understand why I get lines (5) and (6) in the output and not only one of them.
I've no idea. I don't, but since the program has undefined behaviour, anything could happen in principle.
Second, why mc1.print() prints valid values?
It doesn't. It gives undefined behaviour, by printing whatever happens to be in the memory that was once occupied by the dead temporary, if that memory is still accessible. In your case, it just happens that nothing has reused or otherwise invalidated the memory, so you happen to see the values you put there when the temporary was alive.
Shouldn't _ms point to undefined place after mc1(&MyStruct(mc2)) because the place where MyStruct was created (in cast operator) was already unwind?
It points to some memory location which no longer contains a valid object. Typically, the stack frame isn't released until the function returns; and even when it is, the memory typically remains accessible. So accessing a dead object gives you some kind of undefined behaviour, which may not be whatever undefined behaviour you thought it should give.