I have c++ experience for about a year or two but I code the same way I code in Java (simple oop stuff). Now I have this sample code which I don't understand. (it's quite big so I tried to make it shorter, I hope it's clear enough for you guys)
//in .h file
typedef void*(*AnimalCreation)();
//in .cpp
void foo(void* p)
{
AnimalCreation ac = (AnimalCreation)p;
Animal* current_animal = reinterpret_cast<Animal*>(ac());
current_animal->init();
}
//somewhere in another class foo is called
Dog* dog = new Dog(); //Dog is a subclass of Animal
foo((void*)&dog)
What is the purpose of AnimalCreation?
And what's the difference between that and
typedef void(*AnimalCreation)();`//without asterisk after void
What's happening inside foo?
If the expected argument foo receives is always a subclass of Animal why does the programmer need to implement it like in the above and not just foo(Animal*)?
Thanks.
typedef void(*AnimalCreation)();
this declares "AnimalCreation" to be used as type-alias for a pointer to a function which doesn't return any value, while this
typedef void*(*AnimalCreation)();
declares it to be used as a type-alias for a pointer to a function which returns a void pointer, i.e. an address to something you don't know its type.
Inside foo you're receiving such a "generic address" and you're C-casting(potentially unsafe, checked at runtime) it to a function pointer. This is at your own risk: you don't know what that received address is pointing to. And after that you're calling the function and receiving another void pointer which you reinterpret (dangerous) as an Animal object. And then you use it.
A function pointer cannot be a subclass of anything so I don't think the argument in that code is an Animal subclass... rather the subclass to the Animal class is the object returned by that function. Assuming that is also a polymorphic class, you will then be able to call its methods with the virtual inheritance rules. If you intend to check the pointer received by the function call and you're unsure whether it is a subclass of the Animal class, you'd rather be using dynamic_cast.
As a sidenote: converting between function pointers and void* is a bad practice in C++ since you lose valuable type information.
The typedef line is AnimalCreation being defined as a function pointer type
Function foo takes in a void * argument which it casts into an AnimalCreation type (i.e. into the function pointer type). It can then invoke the function via the function pointer. This invocation returns a void * (as per the typedef - the part before the firts bracket is the return type, hence void*) which is then casted to an Animal* by reinterpret_cast.
If you removed the asterisk from the typdef - it would still declare a function pointer type, but now the return value would be void instead of void * (i.e. nothing returned, rather than a pointer). You could still invoke the function via the function pointer, but it would not return anything.
All in all, this is a nice little function pointer tutorial.
EDIT : the big picture of what this code seems to be doing - this is one way of implementing a 'Factory Pattern' in C++ - abstracting the creation of an object, and returning a polymorphic base class pointer to a derived class. Casting between void * and function pointers and reinterpret_cast is not the nicest way to achieve this, for alternatives you could look here
First off, this is quite ugly C-style code.
typedef void*(*AnimalCreation)();
To interpret this, follow the general rule of C & C++ declaration reading: if you type the declaration as an expression, you'll get its type.
*AnimalCreation This means AnimalCreation is a pointer
(*AnimalCreation)() This means *AnimalCreation is a function taking no arguments, so AnimalCreation is a pointer to function taking no arguments
void *(*AnimalCreation)() This means (*AnimalCreation)() is a void* (= pointer to void), so AnimalCreation is a pointer to a function which takes no arguments and returns a void*.
If it was just typedef void (*AnimalCreation)();, it would be a pointer to a function taking no arguments and returning no value (i.e. returning void).
Now, foo().
That takes a void* (pointer to anything) and interprets it as AnimalCreation - as a pointer to function taking no arguments and returning a void*. If the argument passed to foo was actually of that type, all is well. If something else is passed in, the program will exhibit Undefined Behaviour, which means anything can happen. It would most likely crash, as it could be trying to interpret data as code, for example.
foo() calls that function passed in, which returns a void*. foo() then interprets that as a pointer to Animal. If that's what the function actually returned, great. If not, Undefined Behaviour again.
Finally, the call you're showing will force the Undefined Behaviour to happen, because it's passing in the address of a pointer to an object. But, as stated above, foo() will interpret that as the address of a function, and try to call that function. Hilarity ensues.
To summarize, such code is bad and its author should feel bad. The only place you'd expect to see such code is interoperability with a C-style external library, and in such case it should be extremely well documented.
Related
I am trying to write a class that will be appended with some function pointers.
This pointers will be called from another method of this class. I will be storing the function pointers on a void* vector so anything can go on a single vector, instead of a different vector for each type.
I intend to declare a different AppendCallback methods for any different function I need to call from inside the class, for example:
void MyClass:AppendCallback(void (*Callback)())
{
_CallbackVector.push_back((void*)Callback);
_IdVector.push_back(VoidID);
}
void MyClass:AppendCallback(void (*Callback)(uint32_t));
void MyClass:AppendCallback(void (*MyOtherClass::Callback)());
void MyClass:AppendCallback(void (*MyOtherClass::Callback)(uint32_t));
There will be a second vector that only contains identifiers to know what the void* points to, this is going to be assigned also on the AppendCallback Methods.
How can I cast the void pointer again to the function pointers for calling those functions?
Maybe something like this?
void MyClass::Service(uint32_t x)
{
for(uint i = 0; i < _CallbackVector.size(); i++)
{
switch(_IdVector[i])
{
case VoidID: void(*_CallbackVector[i]()); break;
case Uint32ID: void(*_CallbackVector[i](x)); break;
}
}
}
Edit:
Is this a proper way of casting from a void* to a function pointer?
That's not allowed in C++:
Converting a void* to a function pointer directly is not allowed (should not compile using any of the casts) in C++98/03. It is conditionally supported in C++0x (an implementation may choose to define the behavior and if it does define it then it must do what the standard says it should do. A void*, as defined by the C++98/03 standard, was meant to point to objects and not to contain function pointers or member pointers.
And again:
You can't.
You can cast a data pointer to void* and then back to the same pointer type you have started with. std::function is not a pointer type, so the cast is statically invalid, and it's not the same thing you have started with. You have started with a .target of type void()() but it's not a data pointer, it's a function pointer, so casting it to void and back is implementation-defined.
In your specific situation, you could try something like this:
class PointerToFunction {
};
template <typename Type>
class PointerToFunctionType : public PointerToFunction, std::function<Type> {
public:
using std::function<Type>::function; // I think this is the right syntax for this trick: https://softwareengineering.stackexchange.com/a/197901/342247
};
// Now, we can do this:
std::vector<PointerToType*> _CallbackVector;
Basically, we're using an inheritance trick similar to how boost::any/std::any (since C++17) is implemented to store any std::function in a pointer. The only issue is knowing how to convert it back. Doing this properly would depend on how you expected to convert that void* back to begin with (i.e., knowing its type), so I'll leave that part up to you.
I have a class defined as follows:
class A
{
public:
A()
{
fp = &A::f;
}
void (A::*fp)();
void f()
{
cout << "A::f()" << endl;
}
};
In main function, I have object of class A defined, and I would like to call a.fp(). However, I found out that I cannot do this neither with a.fp() nor with (a.fp)(). Finally, (a.*a.fp)(), which is totally strange from syntax point of view, worked.
int main()
{
A a;
(a.*a.fp)();
return 0;
}
Could anybody explain what (a.*a.fp)() actually means and why (a.fp)() doesn't work?
Let's add parentheses to make the grouping explicit:
( a.*(a.fp) )()
a.fp is a regular access to the pointer-to-member fp inside a.
a.*(...) retrieves the member function via indirection, using the pointer to member access operator.
(...)() performs the function call on the "callable" expression in (...).
As to why (a.fp)() doesn't work. It's because pointers to members are not like regular pointers. You need to apply them to an object, an instance of the class. So a.fp only retrieves the pointer-to-member, which is not a callable type on its own. You can't call it without applying to an object, what is achieved by .* to produce a callable expression.
This code accesses the a object in two different ways, for two different purposes. To understand it better, you need to separate the two.
Calling a member function through a pointer-to-member-function requires either .* or ->*, depending on whether you have an actual object or a pointer to an object:
void (A::*afp)() = &A::f;
A a;
(a.*afp)(); // calls A::f on the `a` object
A* ap = &a;
(ap->*afp)() // calls A::f on the `a` object
When the pointer-to-member-function is a member of the class you have to access the pointer with the usual class member access. That is, a.fp is the pointer-to-member-function in the object a. So, combining the two, (a.*a.fp)() calls the member function of a that a.fp points at, and calls it on the a object.
(a.*a.fp)();
a the instance a
a.fp the member of a which is a pointer to member function
*a.fp dereferencing the member function pointer
(a.*a.fp)() invoking the member function on a
The last two steps are actually one (.* is one operator). In general if mem_fun is a member fucntion pointer the syntax to call it is
(a.*mem_fun)();
See also here.
a.fp is a pointer to a member function, where "pointer" is to be understood in the very general sense of "some kind of indirection based on an object".
The pointer has no knowledge about any instance of A - you need an object that it can be "dereferenced" relative to.
That is, you also need a.
Dereferencing any member pointer p relative to a looks like a.*p.
(.* looks like two operators, but it's actually just one, the "pointer-to-member dereference operator").
Since your member function pointer is a.fp, the dereferencing syntax is a.*(a.fp), or more condensed, a.*a.fp.
Then you need to wrap that bunch in parentheses (for precedence reasons) and you get
(a.*a.fp)()
Side note: the following are also valid:
void (A::*function)() = &A::f;
A a;
(a.*function)();
A b;
(a.*b.fp)();
and do the same thing.
Amazingly people may call it feature but I use to say it another bug of C++ that we can call member function through pointer without assigning any object. See following example:
class A{
public:
virtual void f1(){cout<<"f1\n";}
void f2(){cout<<"f2\n";};
};
int main(){
A *p=0;
p->f2();
return 0;
}
Output:
f2
We have checked this in different compilers & platforms but result is same, however if we call virtual function through pointer without object then there occur run-time error. Here reason is obvious for virtual function when object is checked it is not found so there comes error.
This is not a bug. You triggered an Undefined Behavior. You may get anything including the result you expected.
Dereferencing a NULL pointer is undefined behavior.
BTW, there is no thing such as "bug of C++". The bugs may occur in C++ Compilers not in the language it self.
As pointed out, this is undefined behaviour, so anything goes.
To answer the question in terms of the implementation, why do you see this behaviour?
The non-virtual call is implemented as just an ordinary function call, with the this pointer (value null) passed in as paremeter. The parameter is not dereferenced (as no member variables are used), so the call succeeds.
The virtual call requires a lookup in the vtable to get the adress of the actual function to call. The vtable address is stored in a pointer in the data of the object itself. Thus to read it, a de-reference of the this pointer is required - segmentation fault.
When you create a class by
class A{
public:
virtual void f1(){cout<<"f1\n";}
void f2(){cout<<"f2\n";};
};
The Compiler puts the code of member functions in the text area.
When you do p->MemberFunction() then the compiler just deferences p and tries to find the function MemberFunction using the type information of p which is Class A.
Now since the function's code exists in the text area so it is called. If the function had references to some class variables then while accessing them, you might have gotten a Segmentation Fault as there is no object, but since that is not the case, hence the function executes properly.
NOTE: It all depends on how a compiler implements member function access. Some compiler may choose to see if the pointer of object is null before accessing the member function, but then the pointer may have some garbage value instead of 0 which a compiler cannot check, so generally compilers ignore this check.
You can achieve a lot with undefined behavior. You can even call a function which only takes 1 argument and receive the second one like this:
#include <iostream>
void Func(int x)
{
uintptr_t ptr = reinterpret_cast<uintptr_t>(&x) + sizeof(x);
uintptr_t* sPtr = (uintptr_t*)ptr;
const char* secondArgument = (const char*)*sPtr;
std::cout << secondArgument << std::endl;
}
int main()
{
typedef void(*PROCADDR)(int, const char*);
PROCADDR ext_addr = reinterpret_cast<PROCADDR>(&Func);
//call the function
ext_addr(10, "arg");
return 0;
}
Compile and run under windows and you will get "arg" as result for the second argument. This is not a fault within C++, it is just plain stupid on my part :)
This will work on most compilers. When you make a call to a method (non virtual), the compiler translates:
obj.foo();
to something:
foo(&obj);
Where &obj becomes the this pointer for foo method. When you use a pointer:
Obj *pObj = NULL;
pObj->foo();
For the compiler it is nothing but:
foo(pObj);
i.e.:
foo(NULL);
Calling any function with null pointer is not a crime, the null pointer (i.e. pointer having null value) will be pushed to call stack. It is up to the target function to check if null was passed to it. It is like calling:
strlen(NULL);
Which will compile, and also run, if it is handled:
size_t strlen(const char* ptr) {
if (ptr==NULL) return 0;
... // rest of code if `ptr` is not null
}
Thus, this is very much valid:
((A*)NULL)->f2();
As long as f2 is non-virtual, and if f2 doesn't read/write anything out of this, including any virtual function calls. Static data and function access will still be okay.
However, if method is virtual, the function call is not as simple as it appears. Compiler puts some additional code to perform late binding of given function. The late binding is totally based on what is being pointed by this pointer. It is compiler dependent, but a call like:
obj->virtual_fun();
Will involve looking up the current type of obj by virtual function table lookup. therefore, obj must not be null.
i want to see the content of the vtable of the class A, especially the virtual desctructor, but i can not call it through a function pointer.
Here is my code:
typedef void (*fun)();
class A {
public:
virtual func() {printf("A::func() is called\n");}
virtual ~A() {printf("A::~A() is called\n");}
};
//enter in the vtable
void *getvtable (void* p, int off){
return (void*)*((unsigned int*)p+off);
}
//off_obj is used for multiple inherence(so not here), off_vtable is used to specify the position of function in vtable
fun getfun (A* obj, unsigned int off_obj,int off_vtable){
void *vptr = getvtable(obj,off_obj);
unsigned char *p = (unsigned char *)vptr;
p += sizeof(void*) * off_vtable;
return (fun)getvtable(p,0);
}
void main() {
A* ptr_a = new A;
fun pfunc = getfun(ptr_a,0,0);
(*pfunc)();
pfunc = getfun(ptr_a,0,1);
(*pfunc)(); //error occurred here, this is supposed to be the virtual desctrutor, why?
}
Let's suppose for the sake of argument that the vtable in question really is laid out the way you think it is, as a table of ordinary memory addresses, and that when casting those addresses to function pointers, they're callable.
You have at least two problems:
The calling convention for the member functions isn't necessarily the same as for ordinary functions. Microsoft's default calling convention is thiscall, which places a pointer to the object whose method is being called in the ECX register. There's no facility for specifying that manually; the only way to make that happen is by calling a member function in the way member functions are called, which involves syntax like obj.f() or pobj->f(). You can't do that with pointers to functions (not even member-function pointers), unless you write machine code or assembler to get all the low-level details right.
You happen not to hit this problem for func because it doesn't make reference to this (either directly or by implicit reference to other members). The destructor does, though. Destructors are special, and what's actually stored in the vtable is a pointer to a compiler-generated helper function that calls the real destructor and then checks some flags passed as a hidden parameter to determine whether it should free the object's memory. The value that happens to be in ECX doesn't matter for the func call, but it's very important to be right for the ~A call.
Destructors aren't like normal functions. As I mentioned above, the compiler can generate one or more helper functions, and they receive parameters in addition to this. You haven't accounted for that in your code. The compiler generates separate helpers for array and non-array destructors, so right now we don't even know which one you found at index 1 of the vtable. But since you didn't pass it a valid flag parameter, and there's no way to pass it the this value, it doesn't really matter what you find in the vtable anyway.
You can attempt to solve the first problem by specifying a different calling convention, like stdcall. That puts the this parameter back on the stack with the rest of the parameters, and that allows you to pass it when you call the function pointer. For func, fun would need to have a declaration like this:
typedef void (__stdcall * fun)(A*);
Invoke pfunc like this:
pfunc(ptr_a);
To solve the second problem, you'll need to determine the actual order of the vtable functions so you know to find the right destructor helper. And to call it, you'd need a different function-pointer declaration, too. Destructors don't technically have a return type, but void works well enough. You could use something like this:
typedef void (__stdcall * destr)(A*, unsigned flags);
For most of this answer, I've used an article by Igorsk about recognizing certain patterns in a program for the purpose of decompiling it back into C++. Part 2 covers classes.
You don't call the destructor. You call operator delete(), and it figures out the destructor. Calling destructors directly is Undefined Behavior, in the same sense that dereferencing NULL is, i.e. blows up on every platform I've seen.
I wrote a function along the lines of this:
void myFunc(myStruct *&out) {
out = new myStruct;
out->field1 = 1;
out->field2 = 2;
}
Now in a calling function, I might write something like this:
myStruct *data;
myFunc(data);
which will fill all the fields in data. If I omit the '&' in the declaration, this will not work. (Or rather, it will work only locally in the function but won't change anything in the caller)
Could someone explain to me what this '*&' actually does? It looks weird and I just can't make much sense of it.
The & symbol in a C++ variable declaration means it's a reference.
It happens to be a reference to a pointer, which explains the semantics you're seeing; the called function can change the pointer in the calling context, since it has a reference to it.
So, to reiterate, the "operative symbol" here is not *&, that combination in itself doesn't mean a whole lot. The * is part of the type myStruct *, i.e. "pointer to myStruct", and the & makes it a reference, so you'd read it as "out is a reference to a pointer to myStruct".
The original programmer could have helped, in my opinion, by writing it as:
void myFunc(myStruct * &out)
or even (not my personal style, but of course still valid):
void myFunc(myStruct* &out)
Of course, there are many other opinions about style. :)
In C and C++, & means call by reference; you allow the function to change the variable.
In this case your variable is a pointer to myStruct type. In this case the function allocates a new memory block and assigns this to your pointer 'data'.
In the past (say K&R) this had to be done by passing a pointer, in this case a pointer-to-pointer or **. The reference operator allows for more readable code, and stronger type checking.
It may be worthwhile to explain why it's not &*, but the other way around. The reason is, the declarations are built recursively, and so a reference to a pointer builds up like
& out // reference to ...
* (& out) // reference to pointer
The parentheses are dropped since they are redundant, but they may help you see the pattern. (To see why they are redundant, imagine how the thing looks in expressions, and you will notice that first the address is taken, and then dereferenced - that's the order we want and that the parentheses won't change). If you change the order, you would get
* out // pointer to ...
& (* out) // pointer to reference
Pointer to reference isn't legal. That's why the order is *&, which means "reference to pointer".
This looks like you are re-implementing a constructor!
Why not just create the appropriate constructor?
Note in C++ a struct is just like a class (it can have a constructor).
struct myStruct
{
myStruct()
:field1(1)
,field2(2)
{}
};
myStruct* data1 = new myStruct;
// or Preferably use a smart pointer
std::auto_ptr<myStruct> data2(new myStruct);
// or a normal object
myStruct data3;
In C++ it's a reference to a pointer, sort of equivalent to a pointer to pointer in C, so the argument of the function is assignable.
Like others have said, the & means you're taking a reference to the actual variable into the function as opposed to a copy of it. This means any modifications made to the variable in the function affect the original variable. This can get especially confusing when you're passing a pointer, which is already a reference to something else. In the case that your function signature looked like this
void myFunc(myStruct *out);
What would happen is that your function would be passed a copy of the pointer to work with. That means the pointer would point at the same thing, but would be a different variable. Here, any modifications made to *out (ie what out points at) would be permanent, but changes made to out (the pointer itself) would only apply inside of myFunc. With the signature like this
void myFunc(myStruct *&out);
You're declaring that the function will take a reference to the original pointer. Now any changes made to the pointer variable out will affect the original pointer that was passed in.
That being said, the line
out = new myStruct;
is modifying the pointer variable out and not *out. Whatever out used to point at is still alive and well, but now a new instance of myStruct has been created on the heap, and out has been modified to point at it.
As with most data types in C++, you can read it right-to-left and it'll make sense.
myStruct *&out
out is a reference (&) to a pointer (*) to a myStruct object. It must be a reference because you want to change what out points at (in this case, a new myStruct).
MyClass *&MyObject
Here MyObject is reference to a pointer of MyClass. So calling myFunction(MyClass *&MyObject) is call by reference, we can change MyObject which is reference to a pointer. But If we do myFunction( MyClass *MyObject) we can't change MyObject because it is call by value, It will just copy address into a temporary variable so we can change value where MyObject is Pointing but not of MyObject.
so in this case writer is first assigning a new value to out thats why call by reference is necessary.