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

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.

Related

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

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.

Forcing a call to a class operator== to fail if return value is unused on GCC 4.4.7

I would like to know if there is a way to turn the use of a operator== on a class into a compiler error if the result is doing nothing with the result. The reason is to catch a use of the operator== when instead the developer intends to use operator=.
I do not care if the solution is GCC specific, as long as it works on GCC 4.4.7. Solutions can include GCC-specific attributes, compiler pragmas, or a source code file changes on the C++ class given below. Less attractive are changes to compiler options.
See example below. Uncomment the #define DO_STRING_LITERAL_TEST line below and you will see a helpful message from the compiler:
/usr/bin/g++ -MD -DDEBUG -g -ggdb -gstabs+ -O0 -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type main.cpp -c -o main.o
cc1plus: warnings being treated as errors
main.cpp: In function ‘int main(int, char**, char* const*)’:
main.cpp:37: error: comparison with string literal results in unspecified behaviour
Comment the #define DO_STRING_LITERAL_TEST line, but then uncomment the #define DO_STRING_CONTAINER_TEST line. This compiles just fine and I would like it to fail on the line indicated:
foo == " "; // <-- I need this to throw a compiler error
Here is the example code:
#include <iostream>
#include <string>
class StringContainer {
private:
std::string _val;
public:
StringContainer(const char * inString = NULL) : _val(inString ? inString : "") {}
bool operator==(const StringContainer & other) const
{
return _val == other._val;
}
void operator=(const char * other)
{
_val = other;
}
const char * getString() const
{
return _val.c_str();
}
};
int main(int argc, char *argv[], char *const envp[])
{
std::cout << __FILE__ << ":" << __LINE__ << ":" << "main begin" << std::endl;
#define DO_STRING_LITERAL_TEST
#ifdef DO_STRING_LITERAL_TEST
const char * invalidval = "foo bar";
// The following use of == throws a nice compiler error on GCC 4.4.7:
invalidval == " ";
#endif // DO_STRING_LITERAL_TEST
//#define DO_STRING_CONTAINER_TEST
#ifdef DO_STRING_CONTAINER_TEST
StringContainer foo;
foo = "some string";
foo == " "; // <-- I need this to throw a compiler error
std::cout << __FILE__ << ":" << __LINE__ << ":" << "foo contains <" << foo.getString() << ">" << std::endl;
#endif // DO_STRING_CONTAINER_TEST
std::cout << __FILE__ << ":" << __LINE__ << ":" << "main end" << std::endl;
return 0;
} // end main
One answer came very close is at https://stackoverflow.com/a/12416677/257924 . But that specifies use of a function attribute, which looks quite attractive, however the version of the GCC compiler that I am required to use balks at the use of -Werror=unused-result:
cc1plus: error: -Werror=unused-result: No option -Wunused-result
If there was a source-code-only change that temporarily (for some segment of code, perhaps) the unused-result warning, that would be even better. https://freeswitch.org/jira/browse/FS-6850#commentauthor_55299_verbose apparently indicates that "same test with gcc 4.8.3 passes ok, since it supports the param."
This shouldn't be something you verify in code. This should be something that your compiler will do for you. If you need a std::string, you should use a std::string - not a MyStringThatHasThisExtraEqualityCheck.
I'd suggest one of several things:
Bug your favorite gcc developer to get them to implement -Wunused-comparison as per this bug report
Just compile your code with clang, which does support that warning. You can then add -Werror to make it an error. You don't need to run the clang binary, but an extra orthogonal couldn't hurt (just gives you more excuse to slack off).
Use some external static analysis tool to verify this stuff for you.
Write unit tests.
GCC allows the __attribute_warn_unused_result__ on a function. Have you tried it with your class's comparator?
EDIT: Never mind. Skipped over the section where you say that your old GCC version still does not support that attribute.

undefined reference to 'myNamespace::MyClass::myFunc()' [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 7 years ago.
I am having a problem calling functions from my test_dll.dll in an outside c++ main. Working on eclipse cdt luna sr2 64, Windows 7. Using the MinGW toolchain for compilation.
The dll .cpp code :
#include <iostream>
#include "MyClass.h"
namespace myNamespace {
MyClass::MyClass() :a(1) {
std::cout << "MyClass():a(" << this->a << ")"<<std::endl;
}
MyClass::~MyClass() { }
void myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}
}
and it is compiled within eclipse with the following lines :
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o MyClass.o "..\\MyClass.cpp"
g++ -shared -o libtest_dll.dll MyClass.o
My main code is the following :
#include <iostream>
#include "MyClass.h"
using namespace std;
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
myNamespace::MyClass *instance = new myNamespace::MyClass;
instance->myFunc();
return 0;
}
and it is compiled with the following
g++ "-IC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll" "-includeC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll\\MyClass.h" -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\test_main.o" "..\\src\\test_main.cpp"
g++ "-LC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll\\Debug" -o test_main.exe "src\\test_main.o" -llibtest_dll
src\test_main.o: In function `main':
C:\Users\nxa02192\Desktop\MY_WORKSPACE\test_main\Debug/../src/test_main.cpp:20: undefined reference to `myNamespace::MyClass::myFunc()'
collect2.exe: error: ld returned 1 exit status
However, what i don't get is that if i just instanciate the class, it will output the correct a=1 value, as specified in the constructor.
I already specified the include paths to the compiler and the library path and file to the linker, as you can see in the compiling commands. Any Ideas ? Thanks !
Change
void myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}
to
void MyClass::myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}

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?

"Undefined symbols" error in C++

I have Point class that has X, Y and Name as data members. I overloaded
T operator-(const Point<T> &);
This calculates the distance between two points and returns a value
template < typename T>
T Point<T>::operator-(const Point<T> &rhs)
{
cout << "\nThe distance between " << getName() << " and "
<< rhs.getName() << " = ";
return sqrt(pow(rhs.getX() - getX(), 2) + pow(rhs.getY() - getY(), 2));;
}
The main function
int main () {
Point<double> P1(3.0, 4.1, "Point 1");
Point<double> P2(6.4, 2.9, "Point 2");
cout << P2 - P1;
return EXIT_SUCCESS;
}
But the problem is that this program doesn't compile, and I receive this error:
Undefined symbols:
"Point<double>::operator-(Point<double>&)", referenced from:
_main in main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Any help is appreciated...
You can't compile non-specialized templates. You have to put the definition code in headers.
You need to put your Point template class in a .hpp file and include that whenever using a Point.
You have to include templates in each file that uses them, otherwise the compiler cannot generate the code for your specific type.
There is also a precedence between operators, which isn't changed when overloading them. Your code will be treated as
(cout << P2) - P1;
Try this instead
cout << (P2 - P1);