This question already has answers here:
When does invoking a member function on a null instance result in undefined behavior?
(2 answers)
Closed 8 years ago.
I would expect the following code to crash at runtime with a null pointer error:
#include <memory>
#include <iostream>
#include <cassert>
struct Foo {
void echo() {std::cout << "Echo" << std::endl;}
};
int main()
{
std::unique_ptr<Foo> up(new Foo());
up.reset(nullptr);
assert(up.get() == nullptr);
up.get()->echo();
}
however both gcc (4.7/4.8/4.9), msvc (2013 and upcoming 2015) and clang (3.5) happily outputs:
Echo
and assert is not firing so up.get() is nullptr.
You are essentially calling a member function with an invalid object argument - which is generally considered to trigger undefined behavior. However, you are not using this inside the member funtion, so no Segfaults should occur practically.
Try adding a member and accessing that member inside echo. That should crash your program. I.e.
struct Foo
{
int i;
void echo() {std::cout << i << std::endl;}
};
Calling member function through NULL pointer is surely an undefined behavior.
Your call to that member function is successful as you are not making use of this pointer.
Related
This question already has answers here:
Function pointer to member function
(8 answers)
Closed 4 years ago.
I'm trying to create a function pointer. My code:
Header file:
#pragma once
#include <stdio.h>
class my_class
{
private:
int function(int x);
int *(*foo)(int);
public:
my_class();
~my_class();
};
css file:
#include "my_class.h"
int my_class::function(int x) {
return 1;
}
my_class::my_class() {
foo = &function;
}
my_class::~my_class()
{
}
But the line inside my_class::my_class() gives this error:
error C2276: '&': illegal operation on bound member function expression
Putting the mouse cursor over the = in said line makes the following tooltip appear:
a value of type "int (my_class::*)(int x)" cannot be assigned to an entity of type "int *(*)int"
How can I get it to work?
What you think the compiler will do for you is an implicit type cast from a pointer to a member function to a pointer to a normal function. But this is not what happens.
A pointer to a member function is usually not used, because the instance of an object is what is assigned a certain amount of memory and thereby a pointer to a member function might not exactly point to the function and might lead to erroneous results.
You can fix it in two ways:
Define your member function as a static function. Static member functions are not attached to any particular object and can be used without the scope resolution operator.
Another probable fix you can use is to use the this pointer to create a pointer to a member function.
This question already has answers here:
static initialization order fiasco
(4 answers)
Closed 4 years ago.
from this question (still not solved) I come across this new problem,so here I made an example:
//main.cpp
int main() {
return 0;
}
//file1.cpp
#include "b.h"
B b;
//file2.cpp
#include "a.h"
A a;
//a.h
#pragma once
#include<iostream>
#include "b.h"
extern B b;
class A
{
public:
A(){ std::cout << "a cotr" << std::endl;b.Use(); }
};
//b.h
#pragma once
#include<iostream>
class B
{
public:
B() { std::cout << "b ctor"<<std::endl; };
void Use() { std::cout << "use b" << std::endl; }
};
In g++ 6.3.0 the output is:( g++ -o test file1.cpp file2.cpp prac.cpp -std=c++11)
a cotr
use b
b ctor
So from the code example it seems that there's no such guarantee,and probably is an undefined behavior ?Is there anywhere the standard said about this?(I do not think it's a duplicate because this situation is a little different:in the initialization of a,invoke b's member function.)
Is object guaranteed to be initialized before calling its member function?
No, it is your job not to call any non-static member function on invalid object, that includes but not limited to passing nullptr as this, object not created yet or already destroyed object. One of the solution of this situation is to have static local object in a function instead of global one and return reference/pointer to it. That method still have problem with destruction order, but at least half of the problem is gone.
This question already has answers here:
Default constructor with empty brackets
(9 answers)
Closed 7 years ago.
I wonder why the constructor doesn't work/get called in the first case.
#include <iostream>
#include <typeinfo>
class Test{
public:
Test(){ std::cout << "1\n"; };
Test(int){ std::cout << "2\n"; };
};
int main()
{
Test a(); // actually doesn't call the constructor
Test b(1); // "2"
std::cout << (typeid(b).name()) << std::endl; // "4Test"
std::cout << (typeid(a).name()); // "F4TestvE"
return 0;
}
I've also found that typenames of created variables are strange. Can anybody explain such a behavior?
I use mingw gcc 4.7.2 for Windows to compile my projects
Thanks a lot.
Test a();
Oh, that's an instantiation of a, an object of type Test.
Test a();
Oh, that's a declaration for a function of no arguments that returns something of type Test.
Oh, wait...
If you instead construct a new a(), or use an (empty) initialisation list, this ambiguity is avoided.
See Herb Sutter's excellent article for more.
Test a(); is interpreted as a declaration of a function named a that takes no parameters and returns an object of type Test.
To create an object, remove the parentheses:
Test a;
remove the parenthesis after Test a();
it should be like test a;
and it will automatically trigger the constructor with no arguments
This question already has answers here:
Accessing class members on a NULL pointer
(8 answers)
Closed 9 years ago.
Why is it possible to use class member functions on an uninitialized object (at least I believe it's uninitialized). The following runs without error:
// A.h
class A {
public:
explicit A(int n) : n_(n) {};
~A() {};
int foo() {
return n_;
};
int bar(int i) {
return i;
};
private:
int n_;
};
with
// main.cc
#include <iostream>
#include "A.h"
int main(int argc, char **argv) {
A *myClass;
std::cout << myClass->bar(5) << "\n";
}
Now, certainly attempting myClass->foo();fails, but why can we even use bar() when all we've declared is that a pointer to A exists, and is called myClass? Is this acceptable coding style/is there ever a reason to use this approach?
why can we even use bar() when all we've declared is that a pointer to A exists, and is called myClass?
Because, in general, it's impossible for the compiler to tell whether a pointer will be valid at runtime; so it isn't required to diagnose this error. However, in this case, a decent compiler should be able to issue a warning, as long as you're not building with warnings disabled.
Is this acceptable coding style/is there ever a reason to use this approach?
Absolutely not. Dereferencing an invalid pointer gives undefined behaviour.
Because you can't know if the block of memory where myClass is pointing to is an initialized object, it have right syntax, but undefined behavior, however if want to prevent, you should use -Wall or a similar compiler option (depends on your compiler) and it will warn you about the uninitialized pointer.
This question already has answers here:
Accessing class members on a NULL pointer
(8 answers)
Calling class method through NULL class pointer [duplicate]
(10 answers)
Closed 9 years ago.
I created a NULL pointer of class App, but somehow the method of the NULL object(of App) is working. Here is my code:
#include "App.h"
#include <iostream>
using namespace std;
int main()
{
App* pointer = NULL;
pointer->print();
system("pause");
}
Attached the Header file
#pragma once
#include <iostream>
using namespace std;
class App
{
private:
int x;
int y;
public:
App(void);
~App(void);
App(int a, int b)
{
x=a;
y=b;
}
void print()
{
cout<<"hello world"<<endl;
}
};
The running result an the screen in : hello world. Why is that?
Undefined behaviour is just that - undefined. Anything can happen, including the appearance of behaving correctly.
For your case, specifically, you might want to check out the generated assembly from your program. You'll probably find that the compiler has optimized your code and inlined that printout or called it directly rather than actually invoking it through a pointer/table lookup.
Dereferenceing a NULL pointer is undefined behaviour. You should not expect your program not to 'work' just because you do this.
In this case your print function does not 'use' the this pointer so your code executes as you expected. But you should not rely on this, undefined behaviour means exactly what it says.
Invoking a method on a NULL pointer is undefined behavior so anything may happen. You should never count on the fact that the code will always produce this output. Always try to avoid such situations.
It is undefined behavior. The implementation is able to work in this toy example because print does not access member variables and is a non-virtual function.
This is undefined behavior, this thread explains why it most likely works, the basic explanation is that it will probably be transformed into something similar to:
void _App_print( App* this );
and since you are not using this it works.
Because print does not (even implicitly) access any data behind the "this" pointer.