I want to understand exactly which part of a program compiler looks at and which the linker looks at. So I wrote the following code:
#include <iostream>
using namespace std;
#include <string>
class Test {
private:
int i;
public:
Test(int val) {i=val ;}
void DefinedCorrectFunction(int val);
void DefinedIncorrectFunction(int val);
void NonDefinedFunction(int val);
template <class paramType>
void FunctionTemplate (paramType val) { i = val }
};
void Test::DefinedCorrectFunction(int val)
{
i = val;
}
void Test::DefinedIncorrectFunction(int val)
{
i = val
}
void main()
{
Test testObject(1);
//testObject.NonDefinedFunction(2);
//testObject.FunctionTemplate<int>(2);
}
I have three functions:
DefinedCorrectFunction - This is a normal function declared and defined correctly.
DefinedIncorrectFunction - This function is declared correctly but the implementation is wrong (missing ;)
NonDefinedFunction - Only declaration. No definition.
FunctionTemplate - A function template.
Now if I compile this code I get a compiler error for the missing ';'in DefinedIncorrectFunction.
Suppose I fix this and then comment out testObject.NonDefinedFunction(2). Now I get a linker error.
Now comment out testObject.FunctionTemplate(2). Now I get a compiler error for the missing ';'.
For function templates I understand that they are not touched by the compiler unless they are invoked in the code. So the missing ';' is not complained by the compiler until I called testObject.FunctionTemplate(2).
For the testObject.NonDefinedFunction(2), the compiler did not complain but the linker did. For my understanding, all compiler cared was to know that is a NonDefinedFunction function declared. It didn't care for the implementation. Then linker complained because it could not find the implementation. So far so good.
Where I get confused is when compiler complained about DefinedIncorrectFunction. It didn't look for implementation of NonDefinedFunction but it went through the DefinedIncorrectFunction.
So I'm little unclear as to what the compiler does exactly and what the linker does. My understanding is linker links components with their calls. So for when NonDefinedFunction is called it looked for the compiled implementation of NonDefinedFunction and complained. But compiler didn't care about the implementation of NonDefinedFunction but it did for DefinedIncorrectFunction.
I'd really appreciate if someone can explain this or provide some reference.
Thank you.
The function of the compiler is to compile the code that you have written and convert it into object files. So if you have missed a ; or used an undefined variable, the compiler will complain because these are syntax errors.
If the compilation proceeds without any hitch, the object files are produced. The object files have a complex structure but basically contain five things
Headers - The information about the file
Object Code - Code in machine language (This code cannot run by itself in most cases)
Relocation Information - What portions of code will need to have addresses changed when the actual execution occurs
Symbol Table - Symbols referenced by the code. They may be defined in this code, imported from other modules or defined by linker
Debugging Info - Used by debuggers
The compiler compiles the code and fills the symbol table with every symbol it encounters. Symbols refers to both variables and functions. The answer to This question explains the symbol table.
This contains a collection of executable code and data that the linker can process into a working application or shared library. The object file has a data structure called a symbol table in it that maps the different items in the object file to names that the linker can understand.
The point to note
If you call a function from your code, the compiler doesn't put the
final address of the routine in the object file. Instead, it puts a
placeholder value into the code and adds a note that tells the linker
to look up the reference in the various symbol tables from all the
object files it's processing and stick the final location there.
The generated object files are processed by the linker that will fill out the blanks in symbol tables, link one module to the other and finally give the executable code which can be loaded by the loader.
So in your specific case -
DefinedIncorrectFunction() - The compiler gets the definition of the function and begins compiling it to make the object code and insert appropriate reference into Symbol Table. Compilation fails due to syntax error, so Compiler aborts with an error.
NonDefinedFunction() - The compiler gets the declaration but no definition so it adds an entry to symbol table and flags the linker to add appropriate values (Since linker will process a bunch of object files, it is possible this definitionis present in some other object file). In your case you do not specify any other file, so the linker aborts with an undefined reference to NonDefinedFunction error because it can't find the reference to the concerned symbol table entry.
To understand it further lets say your code is structured as following
File- try.h
#include<string>
#include<iostream>
class Test {
private:
int i;
public:
Test(int val) {i=val ;}
void DefinedCorrectFunction(int val);
void DefinedIncorrectFunction(int val);
void NonDefinedFunction(int val);
template <class paramType>
void FunctionTemplate (paramType val) { i = val; }
};
File try.cpp
#include "try.h"
void Test::DefinedCorrectFunction(int val)
{
i = val;
}
void Test::DefinedIncorrectFunction(int val)
{
i = val;
}
int main()
{
Test testObject(1);
testObject.NonDefinedFunction(2);
//testObject.FunctionTemplate<int>(2);
return 0;
}
Let us first only copile and assemble the code but not link it
$g++ -c try.cpp -o try.o
$
This step proceeds without any problem. So you have the object code in try.o. Let's try and link it up
$g++ try.o
try.o: In function `main':
try.cpp:(.text+0x52): undefined reference to `Test::NonDefinedFunction(int)'
collect2: ld returned 1 exit status
You forgot to define Test::NonDefinedFunction. Let's define it in a separate file.
File- try1.cpp
#include "try.h"
void Test::NonDefinedFunction(int val)
{
i = val;
}
Let us compile it into object code
$ g++ -c try1.cpp -o try1.o
$
Again it is successful. Let us try to link only this file
$ g++ try1.o
/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
No main so won';t link!!
Now you have two separate object codes that have all the components you need. Just pass BOTH of them to linker and let it do the rest
$ g++ try.o try1.o
$
No error!! This is because the linker finds definitions of all the functions (even though it is scattered in different object files) and fills the blanks in object codes with appropriate values
I believe this is your question:
Where I get confused is when compiler complained about DefinedIncorrectFunction. It didn't look for implementation of NonDefinedFunction but it went through the DefinedIncorrectFunction.
The compiler tried to parse DefinedIncorrectFunction (because you provided a definition in this source file) and there was a syntax error (missing semicolon). On the other hand, the compiler never saw a definition for NonDefinedFunction because there simply was no code in this module. You might have provided a definition of NonDefinedFunction in another source file, but the compiler doesn't know that. The compiler only looks at one source file (and its included header files) at a time.
Say you want to eat some soup, so you go to a restaurant.
You search the menu for soup. If you don't find it in the menu, you leave the restaurant. (kind of like a compiler complaining it couldn't find the function) If you find it, what do you do?
You call the waiter to go get you some soup. However, just because it's in the menu, doesn't mean that they also have it in the kitchen. Could be an outdated menu, it could be that someone forgot to tell the chef that he's supposed to make soup. So again, you leave. (like an error from the linker that it couldn't find the symbol)
Compiler checks that the source code is language conformant and adheres to the semantics of the language. The output from compiler is object code.
Linker links the different object modules together to form a exe. The definitions of functions are located in this phase and the appropriate code to call them is added in this phase.
The compiler compiles code in the form of translation units. It will compile all the code that is included in a source .cppfile,
DefinedIncorrectFunction() is defined in your source file, So compiler checks it for language validity.
NonDefinedFunction() does have any definition in the source file so the compiler does not need to compile it, if the definition is present in some other source file, the function will be compiled as a part of that translation unit and further the linker will link to it, if at linking stage the definition is not found by the linker then it will raise a linking error.
What the compiler does, and what the linker does, depends on the
implementation: a legal implementation could just store the tokenized
source in the “compiler”, and do everything in the linker.
Modern implementations do put off more and more to the linker, for
better optimization. And many early implementations of templates didn't
even look the template code until link time, other than matching braces
enough to know where the template ended. From a user point of view,
you're more interested in whether the error “requires a
diagnostic” (which can be emitted by the compiler or the linker)
or is undefined behavior.
In the case of DefinedIncorrectFunction, you have provides source text
which the implementation is required to parse. That text contains a
error for which a diagnostic is required. In the case of
NonDefinedFunction: if the function is used, failure to provide a
definition (or providing more than one definition) in the complete
program is a violation of the one definition rule, which is undefined
behavior. No diagnostic is required (but I can't imagine an
implementation that didn't provide one for a missing definition of a
function that was used).
In practice, errors which can be easily detected simply by examining the
text input of a single translation unit are defined by the standard to
“require a diagnostic”, and will be detected by the
compiler. Errors which cannot be detected by the examination of a
single translation unit (e.g. a missing definition, which might be
present in a different translation unit) are formally undefined
behavior—in many cases, the errors can be detected by the linker,
and in such cases, implementations will in fact emit an error.
This is somewhat modified in cases like inline functions, where you're
allowed to repeat the definition in each translation unit, and extremely
modified by templates, since many errors cannot be detected until
instantiation. In the case of templates, the standard leaves
implementations a great deal of freedom: at the least, the compiler must
parse the template enough to determine where the template ends. The
standard added things like typename, however, to allow much more
parsing before instantiation. In dependent contexts, however, some
errors cannot possibly be detected before instantiation, which may take
place at compilation time or at link time—early implementations
favored link time instantiation; compile time instantiation dominates
today, and is used by VC++ and g++.
The missing semi-colon is a syntax error and therefore the code should not compile. This might happen even in a template implementation. Essentially, there is a parsing stage and whilst it is obvious to a human how to "fix and recover" a compiler doesn't have to do that. It can't just "imagine the semi-colon is there because that's what you meant" and continue.
A linker looks for function definitions to call where they are required. It isn't required here so there is no complaint. There is no error in this file as such, as even if it were required, it might not be implemented in this particular compilation unit. The linker is responsible for collecting together different compilation units, i.e. "linking" them.
Ah, but you could have NonDefinedFunction(int) in another compilation unit.
The compiler produces some output for the linker that basically says the following (among other things):
Which symbols (functions/variables/etc) are defined.
Which symbols are referenced but undefined. In this case the linker needs to resolve the references by searching through the other modules being linked. If it can't, you get a linker error.
The linker is there to link in code defined (possibly) in external modules - libraries or object files you will use together with this particular source file to generate the complete executable. So, if you have a declaration but no definition, your code will compile because the compiler knows the linker might find the missing code somewhere else and make it work. Therefore, in this case you will get an error from the linker, not the compiler.
If, on the other hand, there's a syntax error in your code, the compiler can't even compile and you will get an error at this stage. Macros and templates may behave a bit differently yet, not causing errors if they are not used (templates are about as much as macros with a somewhat nicer interface), but it also depends on the error's gravity. If you mess up so much that the compiler can't figure it out where the templated/macro code ends and regular code starts, it won't be able to compile.
With regular code, the compiler must compile even dead code (code not referenced in your source file) because someone might want to use that code from another source file, by linking your .o file to his code. Therefore non-templated/macro code must be syntactically correct even if it is not directly used in the same source file.
Related
I am trying to work around the fact that linker drops the registration in my code.
See this answer for details.
The problem I have with that answer is that the --whole-archive option seems like an overkill for just 1 function call. I would like to avoid huge code bloat that I assume it causes.
I found
attribute((used))
, but that works on compile, not link level.
So I wonder if there is a specific way to tell the linker to not drop specific function call, instead of changing link options for entire program.
for clarification this is my code:
bool dummy = (Register(), false); // Register is never called because linker dropped entire static library
So I wonder if there is a specific way to tell the linker to not drop specific function call, instead of changing link options for entire program.
Your objective is actually to tell the linker not to drop the definition of an unreferenced variable (dummy) in whose
initialiser there is a function call that you wish to ensure is executed by your program.
__attribute__(used) is an attribute of functions, but not of variables, and its effect is to force the compiler to compile the function definition,
even if the function is static and appears unreferenced in the translation unit. In your case:
bool dummy = (Register(), false);
it cannot appear to the compiler that Register is unreferenced - it is called - so __attribute__(used) will
be redundant even if the definition of Register() is in the same translation unit and is static. But whether or
not the definition of Register() is compiled in this translation unit or some other, this call to Register()
will not be linked or executed in the program if this definition of dummy is not linked.
I assume you do not want to write a custom linker script, or to modify the source code so that dummy is referenced.
In that case you need to instruct the linker to postulate an undefined reference to dummy, by
passing --undefined=dummy in its options. This will force it to search libraries for
a definition of dummy, and to link archive members (and/or shared libraries) exactly as if there
actually was an undefined reference to dummy in the first file that is linked. No redundant code will be linked,
as is probable with --whole-archive.
You can pass --undefined=<symbol> to the linker for as many values of <symbol> as
you like. To pass it through gcc/g++, use -Wl,--undefined=<symbol>.
Put it in its own section and in the linker script:
KEEP(sectionname)
edit
That line of code might be reduced to zeroing one register or variable
I have three header files in my project which describe objects Rational, Complex, and RubyObject. The first two are templates. All can be interconverted using copy constructors, which are defined in the header files — except for those that construct Rational and Complex from const RubyObject&s, which are defined in a source file.
Note: Those definitions are there by necessity. If they all go in the headers, you get circular dependency.
A while back, I ran into some unresolved symbol errors with the two copy constructors defined in the source file. I was able to include in the source file the following function
void nm_init_data() {
nm::RubyObject obj(INT2FIX(1));
nm::Rational32 x(obj);
nm::Rational64 y(obj);
nm::Rational128 z(obj);
volatile nm::Complex64 a(obj);
volatile nm::Complex128 b(obj);
}
and then call nm_init_data() from the library entry point in the main source file. Doing so forced these symbols to be linked properly.
Unfortunately, I recently upgraded GCC and the errors are back. In fact, it seems to happen in a slightly different place with GCC 4.6 (e.g., on Travis-CI).
But it's not a version-specific issue (as I had thought before). We see it on Travis CI's Ubuntu-based system, which runs GCC 4.6. But we don't see it on an Ubuntu machine with either GCC 4.8.1 or 4.8.2. But we do see it on a Mac OS X machine with 4.8.2 — and not the same machine with 4.7.2. Turning off optimization doesn't seem to help either.
If I run nm on my library, the symbol is definitely undefined:
$ nm tmp/x86_64-darwin13.0.0/nmatrix/2.0.0/nmatrix.bundle |grep RationalIsEC1ERKNS
U __ZN2nm8RationalIsEC1ERKNS_10RubyObjectE
00000000004ca460 D __ZZN2nm8RationalIsEC1ERKNS_10RubyObjectEE18rb_intern_id_cache
00000000004ca458 D __ZZN2nm8RationalIsEC1ERKNS_10RubyObjectEE18rb_intern_id_cache_0
I'm not sure why there are two defined entries which are subordinate to the undefined symbol, but I also don't know as much as I'd like about compilers.
It also looks like the copy constructor is an undefined symbol for each version of the Rational template:
__ZN2nm8RationalIiEC1ERKNS_10RubyObjectE
__ZN2nm8RationalIsEC1ERKNS_10RubyObjectE
__ZN2nm8RationalIxEC1ERKNS_10RubyObjectE
"Well, that's strange," I thought. "Complex64 and Complex128 are also called in that nm_init_data function, but they both resolve properly — and aren't listed in the nm -u output." So I tried adding volatile before the Rational copy construction as well, thinking that maybe the compiler was optimizing out something we don't want optimized out. But that didn't fix it either, sadly. This did, with a caveat:
void nm_init_data() {
volatile VALUE t = INT2FIX(1);
volatile nm::RubyObject obj(t);
volatile nm::Rational32 x(const_cast<nm::RubyObject&>(obj));
volatile nm::Rational64 y(const_cast<nm::RubyObject&>(obj));
volatile nm::Rational128 z(const_cast<nm::RubyObject&>(obj));
volatile nm::Complex64 a(const_cast<nm::RubyObject&>(obj));
volatile nm::Complex128 b(const_cast<nm::RubyObject&>(obj));
}
The caveat is that now I get the exact same error, but for the Complex objects instead. Argh!
dyld: lazy symbol binding failed: Symbol not found: __ZN2nm7ComplexIdEC1ERKNS_10RubyObjectE
Referenced from: /Users/jwoods/Projects/nmatrix/lib/nmatrix.bundle
Expected in: flat namespace
dyld: Symbol not found: __ZN2nm7ComplexIdEC1ERKNS_10RubyObjectE
Referenced from: /Users/jwoods/Projects/nmatrix/lib/nmatrix.bundle
Expected in: flat namespace
This is completely absurd. Here are the definitions for both of these functions, in the same source file as the nm_init_data() function:
namespace nm {
template <typename Type>
Complex<Type>::Complex(const RubyObject& other) {
// do some things
}
template <typename Type>
Rational<Type>::Rational(const RubyObject& other) {
// do some other things
}
} // end of namespace nm
Hint: One thing that is worth mentioning is that the error doesn't occur when nm_init_data() gets called (i.e., when the library is loaded). It happens much later, during another call to these troublesome functions.
How do I fix this problem once and for all, and others like it?
You claim the following, which I doubt.
Those definitions are there by necessity. If they all go in the headers, you get circular dependency.
In most cases you can solve such a circular entanglement by separating your code into an additional .hpp file, which is included together with the class definition that contains the template definitions anywhere needed.
If your code has a real circular dependency, it could not compile. Usually, if your dependencies seem to be circular, you have to look closer and go down to method level and check which of them would require both types to compile.
So it could be that your types use each other, then compile all in one .cpp file (e.g. via three .hpp includes).
Or there are only pointer to another type, then use forward declarations to ensure, that all templates are resolved.
Or third, you have some method that depend forward and some that depend backward, then put the one kind in one file, the others kind in another, and you are fine again.
Additionally, it seems that you should use a forward declaration for your missing items. I would expect something like the following after the definition of the function. E.g.:
template nm::Complex<nm::RubyObject>::Complex(const nm::RubyObject& other);
Rational, Complex... are templates
copy constructors... are defined in the header files — except for those that construct Rational and Complex from const RubyObject&s, which are defined in a source file.
And therein lies your problem. Since Rational and Complex are templates, all their methods need to be available in your header file.
If they're not, then you might sometimes be able to get away with it depending on the order in which things are called and the order in which things are linked -- but more often you'll get strange errors about undefined symbols, which is exactly what is happening here.
Simply move the definitions of Rational(const RubyObject&) and Complex(const RubyObject&) into the respective headers and everything should just work.
This is probably a stupid question, but I've searched for quite a while now here and on the web and couldn't come up with a clear answer (did my due diligence googling).
So I'm new to programming... My question is, how does the main function know about function definitions (implementations) in a different file?
ex. Say I have 3 files
main.cpp
myfunction.cpp
myfunction.hpp
//main.cpp
#include "myfunction.hpp"
int main() {
int A = myfunction( 12 );
...
}
-
//myfunction.cpp
#include "myfunction.hpp"
int myfunction( int x ) {
return x * x;
}
-
//myfunction.hpp
int myfunction( int x );
-
I get how the preprocessor includes the header code, but how do the header and main function even know the function definition exists, much less utilize it?
I apologize if this isn't clear or I'm vastly mistaken about something, new here
The header file declares functions/classes - i.e. tells the compiler when it is compiling a .cpp file what functions/classes are available.
The .cpp file defines those functions - i.e. the compiler compiles the code and therefore produces the actual machine code to perform those actions that are declared in the corresponding .hpp file.
In your example, main.cpp includes a .hpp file. The preprocessor replaces the #include with the contents of the .hpp file. This file tells the compiler that the function myfunction is defined elsewhere and it takes one parameter (an int) and returns an int.
So when you compile main.cpp into object file (.o extension) it makes a note in that file that it requires the function myfunction. When you compile myfunction.cpp into an object file, the object file has a note in it that it has the definition for myfunction.
Then when you come to linking the two object files together into an executable, the linker ties the ends up - i.e. main.o uses myfunction as defined in myfunction.o.
You have to understand that compilation is a 2-steps operations, from a user point of view.
1st Step : Object compilation
During this step, your *.c files are individually compiled into separate object files. It means that when main.cpp is compiled, it doesn't know anything about your myfunction.cpp. The only thing that he knows is that you declare that a function with this signature : int myfunction( int x ) exists in an other object file.
Compiler will keep a reference of this call and include it directly in the object file. Object file will contain a "I have to call myfunction with an int and it will return to me with an int. It keeps an index of all extern calls in order to be able to link with other afterwards.
2nd Step : Linking
During this step, the linker will take a look at all those indexes of your object files and will try to solve dependencies within those files. If one is not there, you'll get the famous undefined symbol XXX from it. He will then translate those references into real memory address in a result file : either a binary or a library.
And then, you can begin to ask how is this possible to do that with gigantic program like an Office Suite, which have tons of methods & objects ? Well, they use the shared library mechanism. You know them with your '.dll' and/or '.so' files you have on your Unix/Windows workstation. It allows to postpone solving of undefined symbol until the program is run.
It even allows to solve undefined symbol on demand, with dl* functions.
1. The principle
When you write:
int A = myfunction(12);
This is translated to:
int A = #call(myfunction, 12);
where #call can be seen as a dictionary look-up. And if you think about the dictionary analogy, you can certainly know about a word (smogashboard ?) before knowing its definition. All you need is that, at runtime, the definition be in the dictionary.
2. A point on ABI
How does this #call work ? Because of the ABI. The ABI is a way that describes many things, and among those how to perform a call to a given function (depending on its parameters). The call contract is simple: it simply says where each of the function arguments can be found (some will be in the processor's registers, some others on the stack).
Therefore, #call actually does:
#push 12, reg0
#invoke myfunction
And the function definition knows that its first argument (x) is located in reg0.
3. But I though dictionaries were for dynamic languages ?
And you are right, to an extent. Dynamic languages are typically implemented with a hash table for symbol lookup that is dynamically populated.
For C++, the compiler will transform a translation unit (roughly speaking, a preprocessed source file) into an object (.o or .obj in general). Each object contains a table of the symbols it references but for which the definition is not known:
.undefined
[0]: myfunction
Then the linker will bring together the objects and reconciliate the symbols. There are two kinds of symbols at this point:
those which are within the library, and can be referenced through an offset (the final address is still unknown)
those which are outside the library, and whose address is completely unknown until runtime.
Both can be treated in the same fashion.
.dynamic
[0]: myfunction at <undefined-address>
And then the code will reference the look-up entry:
#invoke .dynamic[0]
When the library is loaded (DLL_Open for example), the runtime will finally know where the symbol is mapped in memory, and overwrite the <undefined-address> with the real address (for this run).
As suggested in Matthieu M.'s comment, it is the linker job to find the right "function" at the right place. Compilation steps are, roughly:
The compiler is invoked for each cpp file and translate it to an
object file (binary code) with a symbol table which associates
function name (names are mangled in c++) to their location in the
object file.
The linker is invoked only one time: whith every object file in
parameter. It will resolve function call location from one object
file to another thanks to symbol tables. One main() function MUST
exist somewhere. Eventually a binary executable file is produced
when the linker found everything it needs.
The preprocessor includes the content of the header files in to the cpp files (cpp files are called translation unit).
When you compile the code, each translational unit separately is checked for semantic and syntactic errors. The presence of function definitions across translation units is not considered. .obj files are generated after compilation.
In the next step when the obj files are linked. the definition of functions (member functions for classes) that are used gets searched and linking happens. If the function is not found a linker error is thrown.
In your example, If the function was not defined in myfunction.cpp, compilation would still go on with no problem. An error would be reported in the linking step.
int myfunction(int); is the function prototype. You declare function with it so that compiler knows that you are calling this function when you write myfunction(0);.
And how do the header and main function even know the function definition exists?
Well, this is the job of Linker.
When you compile a program, the preprocessor adds source code of each header file to the file that included it. The compiler compiles EVERY .cpp file. The result is a number of .obj files.
After that comes the linker. Linker takes all .obj files, starting from you main file, Whenever it finds a reference that has no definition (e.g. a variable, function or class) it tries to locate the respective definition in other .obj files created at compile stage or supplied to linker at the beginning of linking stage.
Now to answer your question: each .cpp file is compile into a .obj file containing instructions in machine code. When you include a .hpp file and use some function that's defined in another .cpp file, at linking stage the linker looks for that function definition in the respective .obj file. That's how it finds it.
I am trying to compile large C++ project and I am getting this strange error. I know that it is linking error but couldn't figure out what it is exactly.
test_oqlquery.o:(.rodata._ZTV8r_MarrayIhE[vtable for r_Marray]+0x8): undefined reference to r_Marray<unsigned char>::~r_Marray()'
test_oqlquery.o:(.rodata._ZTV8r_MarrayIhE[vtable for r_Marray<unsigned char>]+0xc): undefined reference tor_Marray::~r_Marray()'
test_oqlquery.o:(.rodata._ZTV8r_MarrayIhE[vtable for r_Marray]+0x28): undefined reference to `r_Marray::print_status(std::basic_ostream >&) const'
What does this error mean ? And, is it possible to see the line number where there error is happening ? How ? I am mainly concerned with what this means ".rodata._ZTV8r_MarrayIhE[vtable for r_Marray]+0x28"
Actually, my error is like this, but dont know why everything inside angle bracket are missing, so replacing them with " ", here is detailed error, it has something to do with template instantiation, as well
test_oqlquery.o:(.rodata._ZTV8r_MarrayIhE[vtable for r_Marray"unsigned char"]+0x8): undefined reference to `r_Marray"unsigned char"::~r_Marray()'
I am using g++ 4.3.3.
Please excuse me, I cannot submit the whole source code here as it is very large and spans over multiple directories.
Thanks a lot.
First, linker errors and compiler errors are different things. Since linker deals with object files rather than source files, compiler errors have a line number but linker errors don't.
Second, it seems that you have declared the destructor for r_Marray but have not implemented it anywhere included in the build. The same thing goes for print_status.
Either you have not defined r_Marray::~r_Marray() and r_Marray::print_status or the cpp file containing these methods were not part of your build process.
If you do have the cpp file with these methods defined, please post your Makefile.
Based on your comment to your question I am assuming that r_Marray is templated class? Do you have the definitions for the r_Marray methods in your header file?
This typically happens if you have declared a method but haven't provided or haven't linked its implementation.
For example you have
class r_Marray {
public:
~r_Marray();
};
and you intended to provide the implementation of r_Marray::~r_Marray() in file r_Marray.cpp but forgot to do it - it will compile fine but not link with the error you see. Or you could have provided the implementation but not include the file with that implementation into the input of the linker.
I am looking after a huge old C program and converting it to C++ (which I'm new to).
There are a great many complicated preprocessor hacks going on connected to the fact that the program must run on many different platforms in many different configurations.
In one file (call it file1.c) I am calling functionA().
And in another file (call it file2.c) I have a definition of functionA().
Unfortunately the exact type of the function is specified by a collection of macros created in a bewildering number of ways.
Now the linker is complaining that:
functionA is an unresolved external symbol.
I suspect that the problem is that the prototype as seen in file1.c is slightly different from the true definition of the function as seen in file2.c.
There is a lot of scope for subtle differences due to mismatches between _cdecl and fastcall, and between with and without __forceinline.
Is there some way to show exactly what the compiler thinks is the type of functionA() as seen by file1.c as opposed to file2.c?
You can pass a flag to the compiler (/P, I think) that causes it to output the complete preprocessed output that is passed to the compiler - you can then open this (huge) file, and search through it and the information you need will be in there, somewhere.
Must you actually convert all the existing C code to C++? This is likely to be a lot of work, especially given what you've described so far.
Instead, you can write new code in C++ and call into the C code using extern "C". For example, in a C++ source file you can:
extern "C" {
#include "old_c_header.h"
}
This changes the linkage so the C++ compiler generates external references to the C code without name mangling, allowing the linker to match everything up.
Normally you should have the expected and the actual signature in the output.
Otherwise you can instruct the compiler to output the results of the preprocessing into a seperate file, cl.exe /p for MSVC and for gcc gcc -E.