C++ class name collision - c++

For the following C++ code, I'm getting unexpected behavior. The behavior was verified with recent GCC, Clang and MSVC++. To trigger it, it is required to split the code among several files.
def.h
#pragma once
template<typename T>
struct Base
{
void call() {hook(data);}
virtual void hook(T& arg)=0;
T data;
};
foo.h
#pragma once
void foo();
foo.cc
#include "foo.h"
#include <iostream>
#include "def.h"
struct X : Base<int>
{
virtual void hook(int& arg) {std::cout << "foo " << arg << std::endl;}
};
void foo()
{
X x;
x.data=1;
x.call();
}
bar.h
#pragma once
void bar();
bar.cc
#include "bar.h"
#include <iostream>
#include "def.h"
struct X : Base<double>
{
virtual void hook(double& arg) {std::cout << "bar " << arg << std::endl;}
};
void bar()
{
X x;
x.data=1;
x.call();
}
main.cc
#include "foo.h"
#include "bar.h"
int main()
{
foo();
bar();
return 0;
}
Expected output:
foo 1
bar 1
Actual output:
bar 4.94066e-324
bar 1
What I expected to happen:
Inside of foo.cc, an instance of X defined within foo.cc is made and through calling call(), the implementation of hook() within foo.cc is called. Same for bar.
What actually happens:
An instance of X as defined in foo.cc is made in foo(). But when calling call, it dispatches not to hook() defined in foo.cc but to hook() defined in bar.cc. This leads to corruption, as the argument to hook is still an int, not a double.
The problem can be solved by putting definition of X within foo.cc in an other namespace than definition of X within bar.cc
So finally the question: There is no compiler warning about this. Neither gcc, nor clang or MSVC++ did even show a warning about this. Is that behavior valid as defined per C++ standard?
The situation seems to be a bit constructed, but it happened in a real world scenario. I was writing tests with rapidcheck, where possible actions on a unit to be tested are defined as classes.
Most container classes have similar actions, so when writing tests for a queue and a vector, classes with names like "Clear", "Push" or "Pop" may come up several times. As these are only required locally, I've put them in directly in the sources where the tests are execute.

The program is Ill-formed, because it violates the One-Definition Rule by having two different definitions for class X. So it is not a valid C++ program. Note that the standard specifically allows compilers not to diagnose this violation. So the compilers are conforming, but the program is not valid C++ and as such has Undefined Behaviour when executed (and thus anything can happen).

You have two identically named, but different, classes X in different compilation units, rendering the program ill-formed, as there are now two symbols with the same name. Since the problem can only be detected during linking, compilers are not able (and not required) to report this.
The only way to avoid this sort of thing, is to put any code that is not meant to be exported (in particular all code that has not been declared in a header file) into an anonymous or unnamed namespace:
#include "foo.h"
#include <iostream>
#include "def.h"
namespace {
struct X : Base<int>
{
virtual void hook(int& arg) {std::cout << "foo " << arg << std::endl;}
};
}
void foo()
{
X x;
x.data=1;
x.call();
}
and equivalently for bar.cc. In fact, this is the main (sole?) purpose of unnamed namespaces.
Simply re-naming your classes (e.g. fooX and barX) may work for you in practice, but is not a stable solution, because there is no guarantee that these symbol names are not used by some obscure third-party library loaded at link- or run-time (now or at some point in the future).

Related

Is it possible for a missing #include to break the program at runtime?

Is there any case, where missing a #include would break the software at runtime, while the build still goes through?
In other words, is it possible that
#include "some/code.h"
complexLogic();
cleverAlgorithms();
and
complexLogic();
cleverAlgorithms();
would both build successfully, but behave differently?
Yes, it's perfectly possible. I'm sure there are lots of ways, but suppose the include file contained a global variable definition which called a constructor. In the first case the constructor would execute, and in the second it wouldn't.
Putting a global variable definition in a header file is poor style, but it's possible.
Yes, that's possible.
Everything concerning #includes happens at compile time. But compile time things can change behavior at runtime, of course:
some/code.h:
#define FOO
int foo(int a) { return 1; }
then
#include <iostream>
int foo(float a) { return 2; }
#include "some/code.h" // Remove that line
int main() {
std::cout << foo(1) << std::endl;
#ifdef FOO
std::cout << "FOO" std::endl;
#endif
}
With the #include, overload resolution finds the more appropriate foo(int) and hence prints 1 instead of 2. Also, since FOO is defined, it additionally prints
FOO.
That's just two (unrelated) examples that came to my mind immediately, and I'm sure there are plenty more.
Just to point out the trivial case, precompiler directives:
// main.cpp
#include <iostream>
#include "trouble.h" // comment this out to change behavior
bool doACheck(); // always returns true
int main()
{
if (doACheck())
std::cout << "Normal!" << std::endl;
else
std::cout << "BAD!" << std::endl;
}
And then
// trouble.h
#define doACheck(...) false
It's pathological, perhaps, but I've had a related case happen:
#include <algorithm>
#include <windows.h> // comment this out to change behavior
using namespace std;
double doThings()
{
return max(f(), g());
}
Looks innocuous. Tries to call std::max. However, windows.h defines max to be
#define max(a, b) (((a) > (b)) ? (a) : (b))
If this was std::max, this would be a normal function call that evaluates f() once and g() once. But with windows.h in there, it now evaluates f() or g() twice: once during the comparison and once to get the return value. If f() or g() was not idempotent, this can cause problems. For example, if one of them happens to be a counter which returns a different number every time....
It's possible to be missing a template specialization.
// header1.h:
template<class T>
void algorithm(std::vector<T> &ts) {
// clever algorithm (sorting, for example)
}
class thingy {
// stuff
};
// header2.h
template<>
void algorithm(std::vector<thingy> &ts) {
// different clever algorithm
}
// main.cpp
#include <vector>
#include "header1.h"
//#include "header2.h"
int main() {
std::vector<thingy> thingies;
algorithm(thingies);
}
Binary incompatibility, accessing a member or even worse, calling a function of the wrong class:
#pragma once
//include1.h:
#ifndef classw
#define classw
class class_w
{
public: int a, b;
};
#endif
A function uses it, and it is ok:
//functions.cpp
#include <include1.h>
void smartFunction(class_w& x){x.b = 2;}
Bringing in another version of the class:
#pragma once
//include2.h:
#ifndef classw
#define classw
class class_w
{
public: int a;
};
#endif
Using functions in main, the second definition changes the class definition. It leads to binary incompatibility and simply crashes at runtime. And fix the issue by removing the first include in main.cpp:
//main.cpp
#include <include2.h> //<-- Remove this to fix the crash
#include <include1.h>
void smartFunction(class_w& x);
int main()
{
class_w w;
smartFunction(w);
return 0;
}
None of variants generates a compile or link time error.
The vice versa situation, adding an include fixes the crash:
//main.cpp
//#include <include1.h> //<-- Add this include to fix the crash
#include <include2.h>
...
These situations are even much more difficult when fixing bug in an old version of program, or using an external library/dll/shared object. That's why sometimes must be followed the rules of binary backward compatibility.
I want to point out that the problem also exists in C.
You can tell the compiler a function uses some calling convention. If you don't, the compiler will have to guess that it uses the default one, unlike in C++ where the compiler can refuse to compile it.
For example,
main.c
int main(void) {
foo(1.0f);
return 1;
}
foo.c
#include <stdio.h>
void foo(float x) {
printf("%g\n", x);
}
On Linux on x86-64, my output is
0
If you omit the prototype here, the compiler assumes you have
int foo(); // Has different meaning in C++
And the convention for unspecified argument lists requires that float should be converted to double to be passed. So although I gave 1.0f, the compiler converts it to 1.0d to pass it to foo. And
according to System V Application Binary Interface AMD64 Architecture Processor Supplement, the double gets passed in the 64 least significant bits of xmm0. But foo expects a float, and it reads it from the 32 least significant bits of xmm0, and gets 0.

Class redefinition: How to wrap methods within class [duplicate]

Is there a way to avoid the Graph:: repetition in the implementation file, yet still split the class into header + implementation? Such as in:
Header File:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
Implementation File:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
I'm guessing this is to avoid lots of "unnecessary typing". Sadly there's no way to get rid of the scope (as many other answers have told you) however what I do personally is get the class defined with all my function prototypes in nice rows, then copy/paste into the implementation file then ctrl-c your ClassName:: on the clip board and run up the line with ctrl-v.
If you want to avoid typing the "Graph::" in front of the printGraph, addEdge etc., then the answer is "no", unfortunately. The "partial class" feature similar to C# is not accessible in C++ and the name of any class (like "Graph") is not a namespace, it's a scope.
No there's not. Not directly at least. You could go for preprocessor tricks, but don't do it.
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
Also, you shouldn't even want to do it. What's the point. Besides it being a C++ rule, it lets you know you're actually implementing a member function.
One option is using. If you have method definitions which are in a cpp file that never gets #included, then using is safe (doesn't affect other files):
foo.h:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
foo.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
main.cpp:
#include "foo.h"
int main ()
{
//Foo foo; <-- error
FooLongNameSpecialisationsParamaters foo;
return 0;
}
No, there is no way to avoid it. Otherwise, how would you know if a given function definition is for a class function or for a static function?
If you are asking if you can define a member function such as Graph::printGraph without specifying the class name qualification, then the answer is no, not the way that you want. This is not possible in C++:
implementation file:
void printEdge(){};
The above will compile just fine, but it won't do what you want. It won't define the member function by the same name within the Graph class. Rather, it will declare and define a new free function called printEdge.
This is good and proper, if by your point of view a bit of a pain, because you just might want two functions with the same name but in different scopes. Consider:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
Which scope should the definition apply to? C++ does not restrict you from having different functions with the same names in different scopes, so you have to tell the compiler what function you're defining.
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
EDIT: I misread your question. This would be an answer to the question whether you can split header-files. It doesn't help you to avoid using LongClassName::-syntaxes, sorry.
The simple answer: You can split up c++-file, but you can not split up header-files.
The reason is quite simple. Whenever your compiler needs to compile a constructor, it needs to know exactly how many memory it needs to allocate for such an object.
For example:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
new Foo() would require the allocation of 12 bytes memory. But if you were allowed to extend your class definitions over multiple files, and hence split header files, you could easily make a mess of this. Your compiler would never know if you already told it everything about the class, or whether you did not. Different places in your code could have different definitions of your class, leading to either segmentation faults or cryptic compiler errors.
For example:
h1.h:
class Foo {
double bar; // 8 bytes
int goo; // 4 bytes
}
h2.h:
#include "h1.h"
class Foo {
double goo; // 8 bytes
} // we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
Carefully check what happens if you first compile main.cpp to main.o, then foo1.cpp to foo1.o and foo2.cpp to foo2.o, and finally link all of them together. This should compile, but the makeFoo() allocates something else then the cleanupFoo() deallocated.
So there you have it, feel free to split .cpp-files, but don't split up classes over header files.

"vtable" linker error (involving a virtual destructor with "=default") - potential bug in Clang 3.1?

I'm getting a linker error in my code. I have pinpointed it down to the bare essentials below.
This code gives the linker error "vtable for Foo", referenced from: Foo::Foo()
class Foo {
public:
Foo();
virtual ~Foo() = default;
};
Foo::Foo() { }
But this code doesn't give any errors:
class Foo {
public:
Foo();
virtual ~Foo() { }
};
Foo::Foo() { }
Why? I thought the = default was supposed to basically do the same thing as those empty square brackets.
Update: I'm using the "Apple LLVM compiler 4.1", a part of Xcode 4.5.2. Could it be a bug in this compiler? It may possibly work on the latest GCC (which Apple isn't shipping anymore though). See comments below for a discussion on compilers.
Update 2: As discussed below, changing the line to virtual inline ~Foo() = default; gets rid of this error. Doesn't this simply have to be a bug? Looks like the compiler doesn't recognize an inline function in this case without explicitly writing out inline.
It appears to be a bug in clang which has been fixed already. You asked at a good time, as a new release should be coming shortly: release candidates are already available. Please give them a try, your example works in the i386-linux binary release, and should work in all of them.
In the Itanium ABI, the v-table (and other RTTI information) is emitted for the translation unit containing the definition of the first virtual method not defined inline in the class, or if there are only virtual methods defined inline, for every translation unit that includes the class. It's then up to the linker to merge the redundant symbols.
It is possible that by specifying = default, Clang does not realize that you have defined the virtual method inline in the class and that each and every TU that includes your file should define the v-table and RTTI info, and instead is waiting for the definition to appear somewhere.
May I suggest putting the definition outside the class ? => Foo::~Foo() = default;
It works for me with g++ 4.7.2. But I have the same problem as you with clang 3.1.
I have 3 files.
Foo.h:
#ifndef FOO_H
#define FOO_H
class Foo {
public:
Foo();
virtual ~Foo() = default;
};
#endif // FOO_H
Foo.cpp:
#include "Foo.h"
Foo::Foo() { }
main.cpp:
#include <iostream>
#include "Foo.h"
using namespace std;
int main()
{
Foo foo;
return 0;
}
But if it is like this, it works with clang as well:
Foo.cpp is empty.
main.cpp
#include <iostream>
#include "Foo.h"
using namespace std;
Foo::Foo() { }
int main()
{
Foo foo;
return 0;
}
So I guess clang has bug during generating the objectfile.

Inline constructors and One Definition Rule

Consider following source files
1.cpp
#include <iostream>
using namespace std;
struct X
{
X()
{
cout << "1" << endl;
}
};
void bar();
void foo()
{
X x;
}
int main()
{
foo();
bar();
return 0;
}
2.cpp
#include <cstdio>
struct X
{
X()
{
printf("2\n");
}
};
void bar()
{
X x;
}
Is program compiled from these files well-formed? What should be in it's output?
I've expected linker error due to violation of One Definition Rule or output "1 2". However it prints out "1 1" when compiled with g++ 3.4 and VC 8.0.
How this can be explained?
This does violate ODR (3.2) - specifically that you can have more than one definition of an inline function, but those definitions must be identical (3.2/5) - and leads to undefined behavior, so anything may happen and the compiler/linker is not required to diagnose that. The most likely reason why you see that behavior is that function calls are inlined and do not participate in linking, so no link error is emitted.
It is undefined behaviour (with no required diagnostic) if inlined functions (such as your class constructor) have different definitions in different translation units.

several definitions of the same class

Playing around with MSVC++ 2005, I noticed that if the same class is defined several times, the program still happily links, even at the highest warning level. I find it surprising, how comes this is not an error?
module_a.cpp:
#include <iostream>
struct Foo {
const char * Bar() { return "MODULE_A"; }
};
void TestA() { std::cout << "TestA: " << Foo().Bar() << std::endl; }
module_b.cpp:
#include <iostream>
struct Foo {
const char * Bar() { return "MODULE_B"; }
};
void TestB() { std::cout << "TestB: " << Foo().Bar() << std::endl; }
main.cpp:
void TestA();
void TestB();
int main() {
TestA();
TestB();
}
And the output is:
TestA: MODULE_A
TestB: MODULE_A
It is an error - the code breaks the C++ One Definition Rule. If you do that, the standard says you get undefined behaviour.
The code links, because if you had:
struct Foo {
const char * Bar() { return "MODULE_B"; }
};
in both modules there would NOT be a ODR violation - after all, this is basically what #including a header does. The violation comes because your definitions are different ( the other one contains the string "MODULE_A") but there is no way for the linker (which just looks at class/function names) to detect this.
The compiler might consider that the object is useless besides its use in Test#() function and hence inlines the whole thing. That way, the linker would never see that either class even existed ! Just an idea, though.
Or somehow, linking between TestA and class Foo[#] would be done inside compilation. There would be a conflict if linker was looking for class Foo (multiple definition), but the linker simply does not look for it !
Do you have linking errors if compiling in debug mode with no optimizations enabled ?