When I am compiling the following program with clang++ version 5.0, it is resulting in
error: initializer on function does not look like a pure-specifier
extern void print(void *ptr);
#define NULL __null
class IInterface
{
public:
virtual void method1() = NULL;
};
int main()
{
void *ptr = NULL;
print(ptr);
return 0;
}
It seems __null is not supported by clang? But some posts in stackoverflow suggests clang supports __null. If so why am I getting this error. Could somebody suggest whats going on here?
Link: https://godbolt.org/z/-f3Kf9
The syntax for pure virtual function is only = 0. For example, virtual void do_stuff() = 0 is allowed, but virtual void do_stuff() = nullptr is not allowed.
Clang does support __null but that compiler internal is not meant to declare virtual functions.
The only reason that NULL might work for pure virtual functions is that some system define it as 0, but you should not rely on that. Some compiler might also use 0LL or (void*)0.
If you can, you should use nullptr instead of NULL for declaring null pointers. This is the best solution and can be emulated in older standards.
For declaring pure virtual functions, use = 0. This is the simplest and the usual way to declare pure virtual functions.
This seems to be some sort of misunderstanding here. Making a virtual function pure is not the same thing as initializing it to a null pointer. In fact, some compilers will set the vtable entry for a pure function to point to a special function called __cxa_pure_virtual or something like that.
Since you are not actually initializing a pointer, you can't use __null here. Not even GCC 4.1 allows it. Nor can you use nullptr, which is the standard replacement for __null. Just write = 0; here.
What is going on here is:
For some reason, you're using a compiler internal (__null) instead of the standard nullptr (at worst, the old NULL was already in the standard and did not need defining by you)
For some reason, you're trying to use __null (or NULL (or nullptr)) as a pure virtual function specifier. You can't do that. It's supposed to be = 0. I believe GCC permits, or used to permit, what you're doing as an extension; Clang doesn't.
Simple as that really!
Your next steps:
Stop using __null for null pointers; use nullptr instead.
Stop using null pointers for pure virtual function specifiers. It's = 0.
Related
I found one more case when compiler thinks that static_cast may return nullptr on non-nullptr argument. It seems that this time there is no undefined behavior, like was before, but maybe I'm missing something.
Here's the code compiled with gcc with -O1 -fPIC -Wnull-dereference -Werror options:
struct IR {
virtual ~IR() = default;
};
struct IF {
virtual ~IF() = default;
virtual void get() {};
};
struct SC : IR, IF {
bool h(); // { return true; };
};
struct HD : public IR {
virtual void g() {
if (r_ && r_->h()) {
static_cast<IF*>(r_)->get();
}
}
SC* r_ = nullptr;
};
bool SC::h() { return true; }
HD hd;
Any one of the following conditions will eliminate potential null pointer dereference warning:
making SC::h() inline;
making IF::get() non-virtual;
changing optimization level from -O1 to -O0;
removing -fPIC option...
So, is there a GCC bug, or still UB in code, or static_cast for non-nullptr can results in nullptr?
Link to godbolt.
If you use -fPIC and don't use an inline function for h, then the compiler can't make any assumptions about the behavior of h because GCC's default semantics are to allow any shared library to override the function with alternative semantics. You can additionally specify -fno-semantic-interposition to allow GCC to optimize under the assumption that other implementations of the function loaded from a shared library will not behave differently.
As far as I understand -Wnull-dereference isn't guaranteed to only warn if there is a definitive null pointer dereference, only if there is a potential one (although documentation seems a bit unclear, see also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86172). The compiler can't be sure that r_->h() doesn't modify r_ for the reason above, and therefore the null pointer check cannot prove that static_cast<IF*>(r_)->get(); won't dereference a null pointer.
The warning doesn't appear for -O0 because it is documented that the warning only works when -fdelete-null-pointer-checks is enabled, which it is only with optimizations enabled.
I guess the warning doesn't appear if get isn't virtual either intentionally because the compiler can be sure that the function call won't actually cause a null dereference in the practical sense even if the object pointer is a null pointer (although it is still UB per standard), or alternatively the function is inlined earlier than the null pointer check is performed. (If the function is virtual the compiler can again make no assumptions about this call, since it could be calling a derived class override instead.)
The related procedure code is provided below.I often see such kind of code in open source projects which can run both on Linux and Windows. Somebody told me that it is to avoid compiling warning. Is it really the case?
class Base
{
public:
virtual void on_publication_matched(Publisher* pub, PublicationMatchedStatus& info)
{
(void)pub;
(void)info;
}
};
I wonder why not define it like this:
class Base
{
public:
virtual void on_publication_matched(Publisher* pub, PublicationMatchedStatus& info){};
};
or
class Base
{
public:
virtual void on_publication_matched(Publisher* pub, PublicationMatchedStatus& info) = 0;
};
Let have a look at the first two examples. They define a function that simply does nothing. The difference lies in the void cast
(void)pub;
(void)info;
which is typically used to avoid the unused-variable warnings by the compiler. It does a cast to void. The expression is discarded afterwards, so effectively e.g. (void)pub does nothing but the compiler won't complain about an unused variable. Since c++17 you can use the maybe unused attribute:
virtual void on_publication_matched([[maybe unused]]Publisher* pub,
[[maybe unused]]PublicationMatchedStatus& info){}
Alternatively, you can also write:
virtual void on_publication_matched(Publisher*,PublicationMatchedStatus&){}
This would also not give a warning. However, I prefer to have descriptive argument names. As remarked by #JaMiT you can use inline comments to get:
virtual void on_publication_matched(Publisher*/*pub*/,
PublicationMatchedStatus& /*info*/){}
Your last example marks the function as purely virtual which is far different from the first to examples. That is you can't create an instance of the pure virtual class. You need to provide an implementation in the derived class to create an instance of it. See also this answer.
This is to avoid unused variable warnings. The statement (void)pub; is a noop (does nothing), yet it still references the variable. Hence, the compiler does not complain that pub is not used.
Other examples do not avoid unused variable warnings and making the member function abstract might not be even desirable or the initial intention.
I get this error
USCENEComponent = GetComponentRotation : nonstandard syntax. Use & to create a member pointer.
when compiling this code:
if (!Player_isDead) {
FVector fwd = GetActorForwardVector();
FVector muzzle = GetMesh()->GetBoneLocation("pinky_01_r");
muzzle += fwd * 155;
AProjectile* bullet = GetWorld()->SpawnActor<AProjectile>(BPProjectile, muzzle, RootComponent->GetComponentRotation); // <<===== error
if (bullet) {
//bullet->Firer = this;
bullet->ProxSphere->AddImpulse(fwd*BulletLaunchImpulse);
}
else {
GEngine->AddOnScreenDebugMessage(0, 5.f, FColor::Yellow, "no bullet actor could be spawnd. is the bullet overlapping something?");
}
}
What should I add? I don't know offhand. Please let me know in detail. ㅠㅠ
GetComponentRotation is a method. What do you want to do with the method? Call it, or take its address? We don't know, nor does the compiler. It guesses you wanted the address. My guess would be that you wanted to call GetComponentRotation. In that case, add the argument list, even if it's empty: RootComponent->GetComponentRotation( ).
USCENEComponent = GetComponentRotation should be USCENEComponent = GetComponentRotation() (or some variant with an appropriate argument list). GetComponentRoation() is a function call; in C++ you can’t call a function without the parentheses, even if it takes no arguments.
The warning is a bit misleading. It’s really aimed at creating a pointer-to-member-function. Like this:
struct C {
void f();
};
void (C::*pmf)() = &C::f;
That bit on the right-hand-side creates a pointer to the member function f of the struct C.
The business about “non-standard syntax” is a Microsoftism. Any reasonable compiler would tell you that you need parentheses to call a function. The reason that Microsoft gives you this warning is that back in the olden days, Microsoft decided that it made sense to be able to create a pointer to member function without mentioning the class name if the context provided it for you and, while you were being lazy, without the &. So this was legal with Microsoft’s compiler:
struct C {
void f();
void g() { void (C::*pmf)() = f; }
};
They even floated a paper at one of the standards meetings suggesting that the standard should allow this syntax. That didn’t go anywhere.
So, having (erroneously) allowed that syntax, they opted for backward compatibility by giving a misleading warning for code that uses their invalid syntax. Formally, that’s okay: the only requirement that the standard imposes for non-conforming code is that the compiler “issue a diagnostic”, and every compiler I know of considers a warning to be a diagnostic.
Im trying to compare the address of two functions for equality. Type of my stored function is known. This system normally works, consider the following code (written as sample not from the program):
virtual bool compare(void *fn2) {
void (*fn)(int);
if(fn==fn2)
return true;
}
However when class functions came into consideration the same method doesn't work.
virtual bool compare(void *fn2) {
void(__thiscall myclass::*fn)(int);
void *fn2;
if(fn==fn2) //error C2440 type cast: cannot convert void* to void(__thiscall...
return true;
}
These functions override a common base class' pure virtual function similar to following:
virtual bool compare(void*) = 0;
Since I cannot use template<> in virtual functions I am out of options. Is there a way (anyway) to unify class functions and regular functions?
Thanks in advance,
Cem
Posix requires the ability to convert function pointers to void*. Standard C++ does not support it.
Member function pointers are not pointers in the ordinary sense, they're more like offsets (even for a non-virtual member function).
Both implementations you show for compare would have Undefined Behavior even if the comparisions and casts were valid, because they fail to return anything in the case where the pointers don't compare equal. Instead of if(blah == bag){ return true; } just do return (blah == bah);.
The problems stem from casting away necessary type information. That's generally not a good idea. Why are you casting away the type information that you need?
Solution: (1) don't cast away necessary type information, and (2) redesign to get rid of that compare function. Also take note of Roger Pate's comment that it seems you're asking about a particular attempted solution rather then the problem. What is the problem?
Cheers & hth.,
This doesn't work because member function pointers are not actually convertible to regular pointers- their size is undefined. In some implementations of some class hierarchies, the member function pointer can be five times the size of a regular pointer. How is this going to work with a comparison to void*?
Situation is following. I have shared library, which contains class definition -
QueueClass : IClassInterface
{
virtual void LOL() { do some magic}
}
My shared library initialize class member
QueueClass *globalMember = new QueueClass();
My share library export C function which returns pointer to globalMember -
void * getGlobalMember(void) { return globalMember;}
My application uses globalMember like this
((IClassInterface*)getGlobalMember())->LOL();
Now the very uber stuff - if i do not reference LOL from shared library, then LOL is not linked in and calling it from application raises exception. Reason - VTABLE contains nul in place of pointer to LOL() function.
When I move LOL() definition from .h file to .cpp, suddenly it appears in VTABLE and everything works just great.
What explains this behavior?! (gcc compiler + ARM architecture_)
The linker is the culprit here. When a function is inline it has multiple definitions, one in each cpp file where it is referenced. If your code never references the function it is never generated.
However, the vtable layout is determined at compile time with the class definition. The compiler can easily tell that the LOL() is a virtual function and needs to have an entry in the vtable.
When it gets to link time for the app it tries to fill in all the values of the QueueClass::_VTABLE but doesn't find a definition of LOL() and leaves it blank(null).
The solution is to reference LOL() in a file in the shared library. Something as simple as &QueueClass::LOL;. You may need to assign it to a throw away variable to get the compiler to stop complaining about statements with no effect.
I disagree with #sechastain.
Inlining is far from being automatic. Whether or not the method is defined in place or a hint (inline keyword or __forceinline) is used, the compiler is the only one to decide if the inlining will actually take place, and uses complicated heuristics to do so. One particular case however, is that it shall not inline a call when a virtual method is invoked using runtime dispatch, precisely because runtime dispatch and inlining are not compatible.
To understand the precision of "using runtime dispatch":
IClassInterface* i = /**/;
i->LOL(); // runtime dispatch
i->QueueClass::LOL(); // compile time dispatch, inline is possible
#0xDEAD BEEF: I find your design brittle to say the least.
The use of C-Style casts here is wrong:
QueueClass* p = /**/;
IClassInterface* q = p;
assert( ((void*)p) == ((void*)q) ); // may fire or not...
Fundamentally there is no guarantee that the 2 addresses are equal: it is implementation defined, and unlikely to resist change.
I you wish to be able to safely cast the void* pointer to a IClassInterface* pointer then you need to create it from a IClassInterface* originally so that the C++ compiler may perform the correct pointer arithmetic depending on the layout of the objects.
Of course, I shall also underline than the use of global variables... you probably know it.
As for the reason of the absence ? I honestly don't see any apart from a bug in the compiler/linker. I've seen inlined definition of virtual functions a few times (more specifically, the clone method) and it never caused issues.
EDIT: Since "correct pointer arithmetic" was not so well understood, here is an example
struct Base1 { char mDum1; };
struct Base2 { char mDum2; };
struct Derived: Base1, Base2 {};
int main(int argc, char* argv[])
{
Derived d;
Base1* b1 = &d;
Base2* b2 = &d;
std::cout << "Base1: " << b1
<< "\nBase2: " << b2
<< "\nDerived: " << &d << std::endl;
return 0;
}
And here is what was printed:
Base1: 0x7fbfffee60
Base2: 0x7fbfffee61
Derived: 0x7fbfffee60
Not the difference between the value of b2 and &d, even though they refer to one entity. This can be understood if one thinks of the memory layout of the object.
Derived
Base1 Base2
+-------+-------+
| mDum1 | mDum2 |
+-------+-------+
When converting from Derived* to Base2*, the compiler will perform the necessary adjustment (here, increment the pointer address by one byte) so that the pointer ends up effectively pointing to the Base2 part of Derived and not to the Base1 part mistakenly interpreted as a Base2 object (which would be nasty).
This is why using C-Style casts is to be avoided when downcasting. Here, if you have a Base2 pointer you can't reinterpret it as a Derived pointer. Instead, you will have to use the static_cast<Derived*>(b2) which will decrement the pointer by one byte so that it correctly points to the beginning of the Derived object.
Manipulating pointers is usually referred to as pointer arithmetic. Here the compiler will automatically perform the correct adjustment... at the condition of being aware of the type.
Unfortunately the compiler cannot perform them when converting from a void*, it is thus up to the developer to make sure that he correctly handles this. The simple rule of thumb is the following: T* -> void* -> T* with the same type appearing on both sides.
Therefore, you should (simply) correct your code by declaring: IClassInterface* globalMember and you would not have any portability issue. You'll probably still have maintenance issue, but that's the problem of using C with OO-code: C is not aware of any object-oriented stuff going on.
My guess is that GCC is taking the opportunity to inline the call to LOL. I'll see if I can find a reference for you on this...
I see sechastain beat me to a more thorough description and I could not google up the reference I was looking for. So I'll leave it at that.
Functions defined in header files are in-lined on usage. They're not compiled as part of the library; instead where the call is made, the code of the function simply replaces the code of the call, and that is what gets compiled.
So, I'm not surprised to see that you are not finding a v-table entry (what would it point to?), and I'm not surprised to see that moving the function definition to a .cpp file suddenly makes things work. I'm a little surprised that creating an instance of the object with a call in the library makes a difference, though.
I'm not sure if it's haste on your part, but from the code provided IClassInterface does not necessarily contain LOL, only QueueClass. But you're casting to a IClassInterface pointer to make the LOL call.
If this example is simplified, and your actual inheritance tree uses multiple inheritance, this might be easily explained. When you do a typecast on an object pointer, the compiler needs to adjust the pointer so that the proper vtable is referenced. Because you're returning a void *, the compiler doesn't have the necessary information to do the adjustment.
Edit: There is no standard for C++ object layout, but for one example of how multiple inheritance might work see this article from Bjarne Stroustrup himself: http://www-plan.cs.colorado.edu/diwan/class-papers/mi.pdf
If this is indeed your problem, you might be able to fix it with one simple change:
IClassInterface *globalMember = new QueueClass();
The C++ compiler will do the necessary pointer modifications when it makes the assignment, so that the C function can return the correct pointer.