I already knew that value of pointer member of class is undefined if it is not initialized in constructor (refer this question). I made a simple example to test it.
main.cc
#include <iostream>
class Foo {
public:
Foo() {
std::cout << __FUNCTION__ << std::endl;
count = 10;
}
void test() {
std::cout << __FUNCTION__ << count << std::endl;
}
private:
int count;
};
class Bar {
public:
void bar() {
std::cout << __FUNCTION__ << std::endl;
std::cout << m_foo << std::endl;
m_foo->test();
m_foo = new Foo();
std::cout << m_foo << std::endl;
}
private:
Foo *m_foo;
};
int main(int argc, char *argv[])
{
std::cout << __FUNCTION__ << std::endl;
Bar bar;
bar.bar();
return 0;
}
If I use g++:
g++ -std=c++11 main.cc -o test
It runs with error as expected:
main
bar
0
Segmentation fault
But, if I change to compile with clang++:
clang++ -std=c++11 main.cc -o test
It runs without any error:
main
bar
0x400920
test-1991643855
Foo
0x1bf6030
As you see, although the pointer is not initialized, it has address not NULL and it can call the function test normally. How can I prevent this error with clang++?
There is no "default value" for pointers. m_foo is not initialized, period. So dereferencing it is undefined behaviour. Be aware that "undefined behaviour" includes "apparently working fine".
Declare m_foo like this:
Foo * m_foo = nullptr;
Dereferencing a nullptr is still undefined behaviour, but on most platforms this will trigger a segmentation fault.
Related
I bulit it with -std=c++17 and tried both g++ and clang++ such as clang++ -std=c++17 <file>. It showed the same results.
unordered_map
Pass an unordered_map to rvalue parameter in a function and assign it to another reference. And the memory is not allowed out of the function.
#include <iostream>
#include <string>
#include <unordered_map>
#include <list>
using namespace std;
typedef unordered_map<string, string> kw_t;
struct Bar {
kw_t &foo;
string bar;
};
list<Bar> bars;
void test(kw_t &&foo) {
cout << &foo["a"] << endl;
bars.emplace_back(Bar { .foo = foo, .bar = "bar" });
cout << &bars.front().foo["a"] << endl;
}
int main()
{
test({{"a", "b"}});
cout << &bars.front().foo["a"] << endl;
return 0;
}
And it has output:
0x1f3ded8
0x1f3ded8
[1] 9776 segmentation fault (core dumped) ./a.o
list
But for other classes, such as list or self defined struct, the code can work.
#include <iostream>
#include <list>
#include <string>
using namespace std;
typedef list<string> args_t;
struct Bar {
args_t &foo;
string bar;
};
list<Bar> bars;
void test(args_t &&foo) {
cout << &foo.front() << endl;
bars.emplace_back(Bar { .foo = foo, .bar = "bar" });
cout << &bars.front().foo.front() << endl;
}
int main()
{
test({"a", "b"});
cout << &bars.front().foo.front() << endl;
return 0;
}
It printed:
0x15a7ec0
0x15a7ec0
0x15a7ec0
Why can the second one work but the first not?
Edit1:
clang version 7.1.0
g++ (GCC) 9.3.0
Why can the second one work but the first not?
In both cases, behaviour of the program is undefined. So, it "can" or "may" or "is allowed to" appear to work (for whatever you perceive as "woking"). Or to not "work". Or to have any other behaviour.
To clarify, the lifetime of the temporary object to which the reference bars.front().foo was bound has ended, and so the reference is invalid. Calling a member function through the invalid reference results in undefined behaviour.
Is it an erroneous behavior for compiler?
No. The compiler is behaving correctly. Your programs however are broken.
I am having difficulty accessing a non-static member function from a function pointer and can't quite figure out my syntax issue. When attempting to compile as seen below I receive "error: fnc_ptr not declared in this scope." and when if the code is modified to not access the function it should point to it compiles and will print out 1 for bar.fn_ptr .To compile I used:
g++ -std=c++11 -Wall example.cpp foo.cpp
The split file structure/namespace is just meant to emulate the same conditions as my original issue.
example.cpp
#include "foo.h"
#include <iostream>
int main(int argc, char* argv[]){
pizza::foo bar;
bar.fn_ptr = &pizza::foo::fnc_one;
std::cout << (bar.*fn_ptr)(1) << std::endl;
return 0;
}
foo.cpp
#include <cmath>
#include "foo.h"
namespace pizza{
double foo::fnc_one(double x){
return pow(x,3) - x + 2;
}
}
foo.h
namespace pizza{
class foo{
public:
double (foo::*fn_ptr)(double);
double fnc_one(double);
foo(){
fn_ptr = 0;
}
};
}
A very similar question can be found here, with additional reference here.
You are missing bar. when referring to fn_ptr which is an attribute of that object. Change it to:
std::cout << (bar.*(bar.fn_ptr))(1) << std::endl;
And it works.
I also recommend reading this FAQ on the subject: https://isocpp.org/wiki/faq/pointers-to-members
I believe the correct syntax is:
//std::cout << (bar.*fn_ptr)(1) << std::endl;
std::cout << (bar.*(bar.fn_ptr))(1) << std::endl;
Using
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609.
I receive the error
slicing.cpp:31:5: error: ‘invoke’ is not a member of ‘std’
slicing.cpp:32:5: error: ‘invoke’ is not a member of ‘std’
When compiling with
g++ -std=c++17 -O2 -g -Wall -c -o slicing.o slicing.cpp
(and the same with -std=gnu++17) code below, modified from Virtual functions and std::function?.
How can I fix this?
I could not find any useful information.
#include <functional>
#include <iostream>
struct base
{
base() {std::cout << "base::base" << std::endl;}
virtual ~base() {std::cout << "base::~base" << std::endl;}
virtual void operator()() {std::cout << "base::operator()" << std::endl;}
};
struct derived1: base
{
derived1() {std::cout << "derived1::derived1" << std::endl;}
virtual ~derived1() {std::cout << "derived1::~derived1" << std::endl;}
virtual void operator()() {std::cout << "derived1::operator()" << std::endl;}
};
struct derived2: base
{
derived2() {std::cout << "derived2::derived2" << std::endl;}
virtual ~derived2() {std::cout << "derived2::~derived2" << std::endl;}
virtual void operator()() {std::cout << "derived2::operator()" << std::endl;}
};
int main(int argc, char* argv[])
{
base* ptr1 = new derived1();
base* ptr2 = new derived2();
std::function<void()> f1 = *ptr1;
std::function<void()> f2(*ptr2);
std::invoke(*ptr1); // calls derived1::operator()
std::invoke(*ptr2); // calls derived2::operator()
//std::invoke(f1); // calls base::operator()
//std::invoke(f2); // calls base::operator()
delete ptr1;
delete ptr2;
return 0;
}
Use the GCC compiler dialect flag -std=c++1z or even better -std=c++17 and upgrade your compiler to GCC 7.
(ed: your compiler seems a bit old so it may not work; notice that GCC 5 was released before the C++17 standard)
With g++ (x86_64-win32-seh-rev1, Built by MinGW-W64 project) 7.2.0
it builds this correctly
#include <iostream>
// C++17
#include <functional>
int Func(int a, int b)
{
return a + b;
}
struct S
{
void operator() (int a)
{
std::cout << a << '\n';
}
};
int main(/*int argc, char* argv[]*/)
{
using namespace std;
std::cout << std::invoke(Func, 10, 20) << '\n'; // 30
std::invoke(S(), 42); // 42
std::invoke([]() { std::cout << "hello\n"; }); // hello
return 0;
}
source: https://www.viva64.com/en/b/0533/#ID0EOHKO
What do I declare with the following definition:
void (*bar)(A*){ }; //1
My first thought was that I declare and define function pointer and a function the pointer point to. But it's wrong, because any call to the bar() leads to a segmentation fault:
#include <iostream>
#include <vector>
#include <memory>
struct A{ };
void foo(A*){ std:cout << "foo" << std::endl; }
void (*bar)(){ };
int main(){
bar();
}
Moreover, I can't imbed any statement into the "definition":
void (*bar)(A*){ std::cout << "foo" << std::endl };
yeilds compile-time error.
So, what does the declaration //1 mean?
This statement:
void (*bar)(A*){ };
declares a variable named bar of type void(*)(A*), ie "pointer to function taking pointer to A and returning void", and zero-initializes it. Thus, it's equivalent to this:
void (*bar)(A*) = nullptr;
Obviously, when calling this bar, a segfault should be no surprise.
It's not possible to declare a function and a pointer to that function in a single declaration.
When you say
void (*bar)(A*){ }; //1
it means "bar" is a function pointer which can point to some function which takes "A*" as parameter.
In your case, it is not pointing to any function yet.
to make it working use,
void (*bar)(A*) = foo;
This means you have declared a function pointer that points to nothing at the moment. You should able to validate that using a debugger.
void (*bar)(A*){ }; //1
You could make the pointer point to a function like this:
void foo(A*){ std::cout << "foo" << std::endl };
bar = &foo;
And call it like this now:
A a;
bar(&a);
Full snippet:
#include <iostream>
class A {};
void (*bar)(A*){};
void foo(A*) { std::cout << " foo " << std::endl;}
int main() {
A a;
bar = &foo;
bar(&a);
}
Your code should be changed to the following code.
#include <iostream>
#include <vector>
#include <memory>
struct A{ };
void foo(A*){ std::cout << "foo" << std::endl; }
void (*bar)(A*);
int main(){
A a;
bar = &foo;
bar(&a);
}
To declare an actual function, get rid of the (*) portion around the function name:
void bar(A*){ std::cout << "foo" << std::endl };
https://ideone.com/UPIYxg
So, what does the declaration //1 mean?
It is just a comment.
Got very weird problem...
I have variable:
Application *ApplicationHandle = NULL;
in Application's function I do:
ApplicationHandle = this;
And ApplicationHandle still remains as NULL... i'm checking this with debugger, before this operation ApplicationHandle is NULL, and 'this' got some address, I can see variables of this class that are valid. After operation ApplicationHandle should be the same pointer as this, but it is still NULL.
How is that possible?
I would suggest moving the static variable out of the global namespace and into the class as a static class member. Here is an example:
// test.hpp
#ifndef TEST_HPP
#define TEST_HPP
class Test
{
public:
// Constructor: Assign this to TestPointer
Test(void) { TestPointer = this; }
// This is just a definition
static Test* TestPointer;
private:
unsigned m_unNormalMemberVariable;
};
#endif /* #ifndef TEST_HPP */
The above code will not work by itself, you need to declare the actual memory of the static member variable (just like you would for a member function).
// test.cpp
#include "test.hpp"
#include <iostream>
// The actual pointer is declared here
Test* Test::TestPointer = NULL;
int main(int argc, char** argv)
{
Test myTest;
std::cout << "Created Test Instance" << std::endl;
std::cout << "myTest Pointer: " << &myTest << std::endl;
std::cout << "Static Member: " << Test::TestPointer << std::endl;
Test myTest2;
std::cout << "Created Second Test Instance" << std::endl;
std::cout << "myTest2 Pointer: " << &myTest2 << std::endl;
std::cout << "Static Member: " << Test::TestPointer << std::endl;
return 0;
}
The static member can be access from any file, not just the file containing the line Test* Test::TestPointer = NULL;. To access the contents of the static pointer, use Test::TestPointer.