what does (.text+0x20): undefined reference to `main' mean [duplicate] - c++

This question already has answers here:
(.text+0x20): undefined reference to `main' and undefined reference to function
(3 answers)
Closed 3 years ago.
Could someone help me with the error that I am getting in the code listing below?
The error is, most likely, about the constructor/destructor:
/usr/bin/ld:
/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/Scrt1.o: in
function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Code listing:
// counter_id.cpp
// Obco class member-function definitions.
#include <iostream>
#include "counter_id.h" // include counter class definition
using namespace std;
// constructor sets object's ID number and descriptive message
Obco::Obco( int ID, string messageString )
: objectID( ID ), message( messageString )
{
cout << "Object " << objectID << "constructor runs"
<< message << endl;
} // end CreateAndDestroy constructor
// destructor
Obco::~Obco()
{
// output newline for certain objects; helps readability
cout << ( objectID == 1 || objectID == 6 ? "\n" : "" );
cout << "Object " << objectID << " destructor runs "
<< message << endl;
} // end ~Obco destructor

You're not just separately compiling (-c), you're trying to do a full link but the linker hasn't found any main function.
For a complete link you need to include all your source or object files in your g++ invocation (especially the one with your main function).
For separately compiling just your one file (to be linked later) you need to add the -c option.

Related

g++ failing when trying to use GDAL library [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 3 months ago.
I just want to compile this easy example of the GDAL library in my Ubuntu 22.04 system using the system-packed g++, version 11.3.0:
#include <iostream>
#include "gdal_priv.h"
#include "cpl_conv.h"
#include "gdal.h"
using namespace std;
int main(int argc, char* argv[])
{
GDALDataset *poDataset;
GDALAllRegister();
poDataset = (GDALDataset *) GDALOpen(argv[1], GA_ReadOnly);
if (poDataset == NULL)
{
cout << "No dataset loaded for file " << argv[1] << ". Exiting." << endl;
return 1;
}
cout << "Driver: "
<< poDataset->GetDriver()->GetDescription()
<< "/"
<< poDataset->GetDriver()->GetMetadataItem(GDAL_DMD_LONGNAME)
<< endl;
cout << "Size: "
<< poDataset->GetRasterXSize() << "x"
<< poDataset->GetRasterYSize() << "x"
<< poDataset->GetRasterCount()
<< endl;
if (poDataset->GetProjectionRef() != NULL)
{
cout << "Projection: " << poDataset->GetProjectionRef() << endl;
}
}
Of course I installed the GDAL libraries, as it can be seen here:
~$ dpkg -l | grep gdal
ii gdal-bin 3.4.1+dfsg-1build4 amd64 Geospatial Data Abstraction Library - Utility programs
ii gdal-data 3.4.1+dfsg-1build4 all Geospatial Data Abstraction Library - Data files
ii libgdal-dev 3.4.1+dfsg-1build4 amd64 Geospatial Data Abstraction Library - Development files
ii libgdal30 3.4.1+dfsg-1build4 amd64 Geospatial Data Abstraction Library
ii python3-gdal 3.4.1+dfsg-1build4 amd64 Python 3 bindings to the Geospatial Data Abstraction Library
Everything seems to be settled and ready to go, but then, when I trigger this g++ command to compile my little program
g++ -I/usr/include/gdal -L/usr/lib -lgdal open_file.cpp -o open_file -g
it fails with this output:
/usr/bin/ld: /tmp/ccU6PwuP.o: in function `main':
/home/jose/Code/concepts/gdal/open_file.cpp:13: undefined reference to `GDALAllRegister'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:14: undefined reference to `GDALOpen'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:29: undefined reference to `GDALDataset::GetRasterXSize()'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:30: undefined reference to `GDALDataset::GetRasterYSize()'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:31: undefined reference to `GDALDataset::GetRasterCount()'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:34: undefined reference to `GDALDataset::GetProjectionRef() const'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:36: undefined reference to `GDALDataset::GetProjectionRef() const'
collect2: error: ld returned 1 exit status
Which doesn't make any sense, because I am indeed passing the GDAL libraries in -I/usr/include/gdal and the definition of the "undefined" references do exist in the multiple .h files there.
Moreover, this works using clang++:
clang++ -I/usr/include/gdal -L/usr/lib -lgdal open_file.cpp -o open_file -g
Did anyone have a similar issue, or can give some hint on where the problem might be? Thank you.
Include paths have nothing to do with the symbols.
-I/usr/include/gdal -L/usr/lib both are not necessary as they are set by default. But you should use #include <gdal/gdal.h>, not just <gdal.h> and certainly not "gdal.h".
Move -lgdal after all other cpp/object files.
In general, it should be g++ <OPTIONS> <OBJECTS> <LIBRARIES> where library A which uses symbols from lib B should appear after B i.e. -lB -lA, the order matters for ld. Because it will use the library to resolve just the currently missing symbols and then will promptly forget the library ever existed. So any newly found unresolved symbols will not be resolved, hence shifting the library arguments "right". One can resolve circular dependencies by repeating libraries more than once.

Absence of compilation error when using parametrized constructor

Today at work I came across a behavior in C++ which I don't understand. I have produced the following example code to illustrate my problem:
#include <string>
#include <iostream>
class MyException
{
public:
MyException(std::string s1) {std::cout << "MyException constructor, s1: " << s1 << std::endl;}
};
int main(){
const char * text = "exception text";
std::cout << "Creating MyException object using std::string(const char *)." << std::endl;
MyException my_ex(std::string(text));
std::cout << "MyException object created." << std::endl;
//throw my_ex;
std::string string_text("exception text");
std::cout << "Creating MyException object using std::string." << std::endl;
MyException my_ex2(string_text);
std::cout << "MyException object created." << std::endl;
// throw my_ex2;
return 0;
}
This code snippet compiles without any errors and produces the following output:
$ g++ main.cpp
$ ./a.out
Creating MyException object using std::string(const char *).
MyException object created.
Creating MyException object using std::string.
MyException constructor, s1: exception text
MyException object created.
Note that for my_ex the constructor I have defined was not called. Next, if I want to actually throw this variable:
throw my_ex;
I get a compilation error:
$ g++ main.cpp
/tmp/ccpWitl8.o: In function `main':
main.cpp:(.text+0x55): undefined reference to `my_ex(std::string)'
collect2: error: ld returned 1 exit status
If I add braces around the conversion, like this:
const char * text = "exception text";
std::cout << "Creating MyException object using std::string(const char *)." << std::endl;
MyException my_ex((std::string(text)));
std::cout << "MyException object created." << std::endl;
throw my_ex;
Then it works as I would have expected:
$ g++ main.cpp
$ ./a.out
Creating MyException object using std::string(const char *).
MyException constructor, s1: exception text
MyException object created.
terminate called after throwing an instance of 'MyException'
Aborted (core dumped)
I have the following questions:
Why does my first example compile? How come I don't get a compilation error?
Why doesn't the code compile, when I try to throw my_ex;?
Why do the braces resolve the problem?
According to most vexing parse, MyException my_ex(std::string(text)); is a function declaration; the function is named my_ex, taking a parameter named text with type std::string, returns MyException. It's not an object definition at all, then no constructor will be called.
Note the error message undefined reference to 'my_ex(std::string)' for throw my_ex; (you're trying to throw a function pointer in fact), which means that can't find the definition of the function my_ex.
To fix it you can add additional parentheses (as you has shown) or use braces which supported from C++11:
MyException my_ex1((std::string(text)));
MyException my_ex2{std::string(text)};
MyException my_ex3{std::string{text}};
The answer is to use {} (braced-init) as much as possible. Sometimes, though, it might be missed inadvertently. Luckily, compilers (like clang, under no extra warning flags) can hint:
warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
MyException my_ex(std::string(text));
^~~~~~~~~~~~~~~~~~~
test.cpp:13:23: note: add a pair of parentheses to declare a variable
MyException my_ex(std::string(text));
^
( )
1 warning generated.
which will immediately point you the issue.

C++ - What's wrong with this separate compilation code? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I have this code that I'm trying to debug. It looks okay to me. But I get an error I don't understand.Here's my code
//struct.h
#ifndef STRUCT_H
#define STRUCT_H
#include <iostream>
using namespace std;
struct Person {
Person();
Person(int a, string n);
Person(const Person &p);
Person &operator=(const Person &p);
~Person();
int age;
string name;
};
#endif
//struct.cc
#include "struct.h"
Person::Person(): age(0), name("noname") {
cout << "Creating default Person" << endl;
}
Person::Person(int a, string n): age(a), name(n) {
cout << "Creating: " << name << "," << age << endl;
}
Person::Person(const Person &p) {
name = p.name;
age = p.age;
}
Person& Person::operator=(const Person &p) {
Person person;
person.name = p.name;
return person;
}
Person::~Person() {
cout << "Destroying: " << name << "," << age << endl;
}
//structMain.cc
#include "struct.h"
#include <iostream>
using namespace std;
int main() {
Person one(21, "Zuhaib");
cout << "I am " << one.name << ". I am " << one.age << " years old" << endl;
Person two;
cout << "I am " << two.name << ". I am " << two.age << " years old" << endl;
two = one;
cout << "I am " << two.name << ". I am " << two.age << " years old" << endl;
}
I compile with
g++ -c struct.cc
g++ -c structMain.cc
g++ -o struct.o structMain.o
I then get the following error
structMain.o: In function `main':
structMain.cc:(.text+0x3b): undefined reference to `Person::Person(int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
structMain.cc:(.text+0xb5): undefined reference to `Person::Person()'
structMain.cc:(.text+0x11e): undefined reference to `Person::operator=(Person const&)'
structMain.cc:(.text+0x180): undefined reference to `Person::~Person()'
structMain.cc:(.text+0x18c): undefined reference to `Person::~Person()'
structMain.cc:(.text+0x1b8): undefined reference to `Person::~Person()'
structMain.cc:(.text+0x1e3): undefined reference to `Person::~Person()'
structMain.cc:(.text+0x1f4): undefined reference to `Person::~Person()'
collect2: ld returned 1 exit status
I think I included all the right files. I double checked the declarations and definitions. I'm just not sure why these errors are coming up. It looks fine to me.
Also, in the main function, what happens at the line
two = one;
I wonder this because, I've overloaded the operator=, but I've also defined the copy constructor which also executes when "=" is encountered. So in the above case, does operator= execute or the copy constructor.
Any help would be appreciated.
Thanks
When you use:
g++ -o struct.o structMain.o
g++ tries to produce an executable by using the code from structMain.o and put the resulting executable in struct.o. Since structMain.o does not have all the object code to create the executable, you get the linker errors.
You need to use:
g++ -o MyProgram struct.o structMain.o
Here, g++ tries to produce an executable by using the code from struct.o and structMain.o and put the resulting the executable in MyProgram. Assuming you have all the required object code in those two files, that should work.
g++ -o struct.o structMain.o
This tells g++ to take the object code in structMain.o, turn it into an executable, and name that executable struct.o.
As your compiler does exactly what you tell it to, you have just overwritten the object code in struct.o, which happened to hold the definition of your Person class, so yes, the references to that class by structMain.o remain unresolved.
What you want is:
g++ struct.o structMain.o
...or give an explicit output name that is not also the name of one of your input files...
g++ -o someGuessedExecutableName struct.o structMain.o
A common convention is to name a source file after the class it defines, i.e. name it Person.cc and Person.o instead of struct.cc / struct.o... which would have made that error more visible.

Cygwin + Gdb Simple_Program

I wrote this simple program in cygwin:
#include <iostream>
int main()
{
int a;
float b;
std::cout << "Podaj liczbe calkowita: ";
std::cin >> a;
std::cout << "Podaj liczbe rzeczywista: ";
std::cin >> b;
std::cout << "Liczba a = " << a << std::endl;
std::cout << "Liczba b = " << b << std::endl;
return 0;
}
When I try to debug it with gdb, (compiling with -g option), and I get this as my output:
g++ -o -g test test.cpp
test: In function `mainCRTStartup':
/usr/src/debug/cygwin-2.4.1-1/winsup/cygwin/crt0.c:23: multiple definition of `mainCRTStartup'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/../../../../lib/crt0.o:/usr/src/debug/cygwin-2.4.1-1/winsup/cygwin/crt0.c:23: first defined here
test: In function `mainCRTStartup':
/usr/src/debug/cygwin-2.4.1-1/winsup/cygwin/crt0.c:23: multiple definition of `WinMainCRTStartup'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/../../../../lib/crt0.o:/usr/src/debug/cygwin-2.4.1-1/winsup/cygwin/crt0.c:23: first defined here
test:cygming-crtbegin.c:(.text+0x60): multiple definition of `__gcc_register_frame'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/crtbegin.o:cygming-crtbegin.c:(.text+0x10): first defined here
test:cygming-crtbegin.c:(.text+0xd0): multiple definition of `__gcc_deregister_frame'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/crtbegin.o:cygming-crtbegin.c:(.text+0x80): first defined here
test:crt0.c:(.data+0x0): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/crtbegin.o:cygming-crtbegin.c:(.data+0x0): first defined here
test:crt0.c:(.text+0x50): multiple definition of `.weak._Jv_RegisterClasses.__dso_handle'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/crtbegin.o:cygming-crtbegin.c:(.text+0x0): first defined here
test:crt0.c:(.idata+0x1d0): multiple definition of `__imp__ZSt3cin'
test:crt0.c:(.idata+0x1d0): first defined here
test:crt0.c:(.idata+0x1d8): multiple definition of `__imp__ZSt4cout'
test:crt0.c:(.idata+0x1d8): first defined here
/tmp/ccG5Ono8.o:test.cpp:(.text+0x0): multiple definition of `main'
test:test.cpp:(.text+0xe0): first defined here
/tmp/ccG5Ono8.o:test.cpp:(.rdata$.refptr._ZSt4cout[.refptr._ZSt4cout]+0x0): multiple definition of `.refptr._ZSt4cout'
test:test.cpp:(.rdata+0xb0): first defined here
/tmp/ccG5Ono8.o:test.cpp:(.rdata$.refptr._ZSt3cin[.refptr._ZSt3cin]+0x0): multiple definition of `.refptr._ZSt3cin'
test:cygming-crtbegin.c:(.rdata+0xa0): first defined here
/tmp/ccG5Ono8.o:test.cpp:(.rdata$.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_[.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_]+0x0): multiple definition of `.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_'
test:test.cpp:(.rdata+0xc0): first defined here
/tmp/ccG5Ono8.o:test.cpp:(.rdata$.refptr.__dso_handle[.refptr.__dso_handle]+0x0): multiple definition of `.refptr.__dso_handle'
test:test.cpp:(.rdata+0xd0): first defined here
/tmp/ccG5Ono8.o:test.cpp:(.rdata$.refptr._ZNSt8ios_base4InitD1Ev[.refptr._ZNSt8ios_base4InitD1Ev]+0x0): multiple definition of `.refptr._ZNSt8ios_base4InitD1Ev'
test:cygming-crtbegin.c:(.rdata+0x90): first defined here
/tmp/ccG5Ono8.o:test.cpp:(.rdata$.refptr._ZSt3cin[.refptr._ZSt3cin]+0x0): multiple definition of `__fu0__ZSt3cin'
test:cygming-crtbegin.c:(.rdata+0xa0): first defined here
/tmp/ccG5Ono8.o:test.cpp:(.rdata$.refptr._ZSt4cout[.refptr._ZSt4cout]+0x0): multiple definition of `__fu1__ZSt4cout'
test:test.cpp:(.rdata+0xb0): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/crtbegin.o:cygming-crtbegin.c:(.text+0x35): undefined reference to `_Jv_RegisterClasses'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/crtbegin.o:cygming-crtbegin.c:(.text+0x35): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_Jv_RegisterClasses'
collect2: error: ld returned 1 exit status
./test.exe
Any ideas on why I am getting this?

Getting a roll-your-own patch for std::to_string() to work properly with doubles on an old compiler [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I'm patching up security flaws in a 15-20 year old system that hasn't been maintained for 10 years. As such, most of my "patches" are really work arounds and kludges because a real solution would erode the integrity of a working (if insecure) system. One of the "patches" I applied was related to my old compiler not being able to find to_string() within std, which works pretty well, but not perfectly.
Somewhere in these thousands of lines of code, I try to convert a double using patch::to_string(), and it fails to compile with the following error:
g++ -o main -Wall -g -Wextra -pedantic main.o veracodefunctions.o
main.o: In function `main':
/home/(omited for privacy)/2_Test/main.cpp:8: undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> > patch::to_string<double>(double const&)'
collect2: ld returned 1 exit status
*** Error code 1
clearmake: Error: Build script failed for "main"
Below is the original implementation of the patch I used, which I got from the above Stack Overflow post, and should work:
#include <string>
#include <sstream>
namespace patch
{
template < typename T > std::string to_string( const T& n )
{
std::ostringstream stm ;
stm << n ;
return stm.str() ;
}
}
#include <iostream>
int main()
{
std::cout << patch::to_string(1234) << '\n' << patch::to_string(1234.56) << '\n' ;
}
The patch by cMinor has this main() at the bottom of it that is supposed to illustrate that it works with both int and double values, but for some reason mine only works with int, and not with double. Here is my implementation:
patch.h:
8 #include <string>
...
25 namespace patch
26 {
27 template < typename T > std::string to_string( const T& n );
28 }
patch.cpp:
6 #include <string>
7 #include <sstream>
8 #include <stdexcept>
9 #include "patch.h"
...
41 namespace patch
42 {
43 template < typename T > std::string to_string( const T& n )
44 {
45 std::ostringstream stm;
46 stm << n;
47 return stm.str();
48 }
49 }
main.cpp:
2 #include <iostream>
3 #include "patch.h"
4
5 int main () {
6
7 std::cout << "\"12345\" to string is: " << patch::to_string(12345) << std::endl;
8 std::cout << "\"12.345\" to string is: " << patch::to_string(12.345) << std::endl;
9 return 0;
10
11 }
And just so you don't have to scroll, here is the compile error again:
g++ -o main -Wall -g -Wextra -pedantic main.o veracodefunctions.o
main.o: In function `main':
/home/(omited for privacy)/2_Test/main.cpp:8: undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> > patch::to_string<double>(double const&)'
collect2: ld returned 1 exit status
*** Error code 1
clearmake: Error: Build script failed for "main"
Any insight would be much appreciated!
You only declared to_string() in the header, and defined it in the cpp files. While this is the normal way with non-template functions, this is incorrect with templates. You need to place the definition (the actual implementation) in the .h header file, not in the .cpp file.
patch.h:
#include <string>
#include <sstream>
#include <stdexcept>
namespace patch
{
template < typename T > std::string to_string( const T& n )
{
std::ostringstream stm;
stm << n;
return stm.str();
}
}
When you instantiate a header type, the compiler will create a new class for that instantiation. IF the implementation of your function is not in a header, it will not be accessible at compile time which is why you are getting a linker error.
This question has been mostly answered here:
Why can templates only be implemented in the header file?