... undefined reference to ... collect2: ld returned 1 exit status
Solution 1
Why do you have these lines in error.cpp?
#ifdef error_h
...
#endif
Since the preprocessor symbol error_h
is not defined the entire contents of error.cpp are being omitted by the preprocessor. Remove those lines and your program will link successfully.
You seem to have a misunderstanding of how (and maybe why) #include
guards are to be used. Refer to this answer for an explanation.
Also, there's no need to include iostream and cstdio in error.h, since that file is not using anything declared in either of those headers. Those files should be included in error.cpp.
Solution 2
error_h
is not defined in error.cpp, so all your file content gets #ifdef'd away.
In essence, you're compiling error.cpp as an empty file.
Solution 3
Remove this
#ifdef error_h
and the corresponding #endif
from error.cpp
. Otherwise, here:
$ g++ -c error.cpp foobar.cpp
error.cpp
is essentially empty. This is because at that stage error_h
is not defined. So you are not compiling the implementation (it would work if you had included error.h
before the #ifdef
, but there is no reason to have that in the .cpp
file anyway).
user1358
Updated on June 05, 2022Comments
-
user1358 almost 2 years
I have the following 3 files:
error.h
#ifndef error_h #define error_h #include <string> #include <iostream> #include <cstdio> void Error(std::string msg); #endif
error.cpp
#ifdef error_h #include "error.h" void Error(std::string msg) { std::cerr << "\n=========================================================\n" << msg << "\n=========================================================\n"; exit(EXIT_FAILURE); } #endif
foobar.cpp
#include "error.h" int main() { for(int i=0; i<99; i++) if(i==55) Error("this works"); return 0; }
Now I do:
$ g++ -c error.cpp foobar.cpp $ g++ error.o foobar.o -o exampleprogram
And I get:
foobar.o: In function `main': foobar.cpp:(.text+0x4b): undefined reference to `Error(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)' collect2: ld returned 1 exit status
What am I doing wrong? What do I need to understand to resolve this, and similar issues in the future without asking questions? Thanks!
-
user1358 over 11 yearsThank you! I have been doing a lot of ".cpp including" of template implementations lately and I just typed these without thinking and overlooked them the whole time. You mentioned iostream and cstdio includes... does this mean that I have to scatter around some of the includes? Some in the .h and some in the .cpp? Is #include <string> needed by the function prototype? Isn't there a way of bundleing all the includes for a .h and .cpp in general? Thanks again.
-
Praetorian over 11 years@user1358 Best practice is to only include the headers that are actually needed in that file, so yes, includes tend to be scattered around. There's nothing incorrect about including both the headers in error.h, but when you include error.h in main.cpp, the preprocessor will include the files in the translation unit created from main.cpp and the compiler will have to process those headers as well. Not really a concern in small projects, but for large projects this can significantly impact build times.
-
user1358 over 11 yearsYour explanations helped a lot. Thank you very much.