I have 3 files; main.cpp (which contains main()), FileWriter.h, and FileWriter.cpp. I'm using g++ (version Debian 4.9.2-10) on Debian Jessie. My project contains .cpp files in '/root/dev/Practice/src/', and a single header (FileWriter.h) in '/root/dev/Practice/include/'. The compilation of the two object files works, but the linking to an executable complains about undefined reference to main(), although I do indeed have a seemingly valid one defined in 'main.cpp'.
Here's the output of my make file (which is in the root '/root/dev/Practice/' directory):
g++ -c -g -Wall -o src/FileWriter.o src/FileWriter.cpp
g++ -c -g -Wall -o src/main.o src/FileWriter.cpp
g++ src/FileWriter.o src/main.o -o bin/Practice
/usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu/crt1.o: In function '_start'"
/build/glibc-J1NNmk/glibc-2.19/csu/../sysdeps/i386/start.S:111: undefined reference to 'main'
collect2: error: ls returned 1 exit status
Makefile:10: recipe for target 'bin/Practice' failed
Here's the contents of my main.cpp file:
#include <string>
#include <iostream>
#include "/root/dev/Practice/include/FileWriter.h"
int main() {
std::cout << "Hello!" << std::endl;
FileWriter * fw = new FileWriter("foofile");
fw->AddLine("CRAP!");
fw->AddLine("NO!");
return 0;
}
My FileWriter.h:
#ifndef FILEWRITER_H_
#define FILEWRITER_H_
#include <string>
#include <iostream>
class FileWriter{
public:
FileWriter(std::string);
~FileWriter();
void AddLine(std::string);
private:
std::string fileLocation;
std::ofstream *filestream;
};
#endif /* FILEWRITER_H_ */
...and my FileWriter.cpp:
#include "/root/dev/Practice/include/FileWriter.h"
#include <fstream>
// g++ linker error if 'inline' not included - why?
inline FileWriter::FileWriter(std::string fileName)
{
this->fileLocation = fileName;
const char * x = this->fileLocation.c_str();
this->filestream = new std::ofstream();
this->filestream->open(x, std::ios::out | std::ios::app);
}
inline FileWriter::~FileWriter()
{
this->filestream->close();
}
inline void FileWriter::AddLine(std::string line)
{
*this->filestream << line << std::endl;
}
This line:
g++ -c -g -Wall -o src/main.o src/FileWriter.cpp
should be:
g++ -c -g -Wall -o src/main.o src/main.cpp
I don't have access to this compiler, but in the past if you had main() in a C++ file you needed to "decorate" it with __cdecl
int __cdecl main() {
Try that? Or:
extern "C" int main() {
Related
I want to write a shared library and I want to get a compiler/linker error if I forgot to implement some functions.
Consider the following case:
test.h
class Test {
public:
Test();
};
test.cpp
#include "test.h"
main.cpp
#include "test.h"
int main() {
new Test();
}
If I create a library with this command gcc -c -fpic test.cpp && g++ -shared -o libtest.so -Wl,--no-undefined -Wl,--no-allow-shlib-undefined test.o there is no error message, but the library is broken. Is there a way to force the creation of a not broken library?
Edit: adding additional flag, but doesn't change result
These codes have been modified:
test.h :
class Test {
public:
Test();
};
test.cpp :
#include "test.h"
Test::Test(){} // you must implement the constructor
You must have to implement the constructor, and if not, you get an error "undefined reference to `Test::Test()'".
main.cpp :
#include <iostream>
#include "test.h"
using namespace std;
int main(void)
{
Test* t = new Test(); // you must define a pointer
cout << "test* was created: " << t << endl;
delete t;
t = nullptr;
return 0;
}
Now all the code is OK. Then we create a shared-library with the following command:
g++ -shared -o test.so -fPIC test.cpp
Finally, we compile the main.cpp file at the same time as referring to the test.so shared-library and get the exe output, by the command below:
g++ -g main.cpp test.so -o test.exe
I'm back to C++ after a lapse of several years with a proof of concept. I have a hpp file that defines a class, a cpp file with the class methods, and a main.cpp for testing. I'm attempting to create a tcp server that runs in its own thread (only called once). I started with all the code in the same cpp file and got it to work but I get compile errors now that I've put the class and the methods in their own files.
I've searched but not found anything that works. I've tried using extern, the 'singleton' method, etc. which all result in various error messages. I know that I'm not providing a correct reference to the methods.
tcpserver.hpp:
#ifndef __TCP_SERVER_HPP_INCLUDED__
#define __TCP_SERVER_HPP_INCLUDED__
#include <string>
class Server {
public:
static void *tcp_server(void * dummy);
static void hello();
static int parseCmd(const char *cmd, char *reply);
static int copystring(char *reply, const char *msg);
private:
};
#endif
tcpserver.cpp, with class methods as stubs:
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include <cstring> // Needed for memset
#include <sys/socket.h> // Needed for the socket functions
#include <netdb.h> // Needed for the socket functions
#include <string.h>
#include "tcpserver.hpp"
int Server::parseCmd(const char *cmd, char *reply) {
//does stuff
}
int Server::copystring(char *dst, const char *src) {
// does stuff
return (int) ((std::string) dst).length();
}
void Server::hello() {
std::cout << "Server says 'hello'." << std::endl;
}
void *Server::tcp_server(void * dummy) {
const char *port = "5555";
// does a lot of stuff
}
main.cpp:
#include <iostream>
#include <pthread.h>
#include "tcpserver.hpp"
int main() {
Server server;
server.hello(); // 'Canary' method FIRST ERROR
// Initialize and set thread joinable
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_t serverthread;
int rc;
// **** tcp_server method must be static ****
rc = pthread_create(&serverthread, NULL, server.tcp_server, NULL);
if (rc){
std::cout << "Error:unable to create thread," << rc << std::endl;
exit(-1);
}
std::cout << "Main() started thread." << std::endl;
pthread_attr_destroy(&attr);
void *status;
rc = pthread_join(serverthread, &status);
if (rc){
std::cout << "Error:unable to join," << rc << std::endl;
exit(-1);
}
return 0 ;
}
makefile:
all : main.o tcpserver.o
g++ -std=c++11 -o tcpserver main.o tcpserver.o
tcpserver.o: tcpserver.cpp tcpserver.hpp
g++ -std=c++11 tcpserver.hpp
main.o : main.cpp tcpserver.hpp
g++ -std=c++11 main.cpp -lpthread
clean:
rm -f tcpserver.o main.o tcpserver
Your object file compilation is incorrect:
tcpserver.o: tcpserver.cpp tcpserver.hpp
g++ -std=c++11 tcpserver.hpp
main.o : main.cpp tcpserver.hpp
g++ -std=c++11 main.cpp -lpthread
These rules don't indicate that you're building object files, they both say that they're independently building and linking applications. That's why you're getting linker errors - you're not actually linking the result of compiling main.cpp with tcpserver.o.
You need to provide -c to tell gcc that you don't want to link, that you're just compiling. You also need to provide -o to tell it where to output the results. Lastly, you're trying to compile tcpserver.hpp instead of tcpserver.cpp:
tcpserver.o: tcpserver.cpp tcpserver.hpp
g++ -std=c++11 -c tcpserver.cpp -o tcpserver.o
main.o : main.cpp tcpserver.hpp
g++ -std=c++11 -c main.cpp -o main.o
Or, shorter:
%.o : %.cpp tcpserver.hpp
g++ -std=c++11 -c $< -o $#
Also, this rule is bad:
all : main.o tcpserver.o
g++ -std=c++11 -o tcpserver main.o tcpserver.o
The target of the rule is all, but it's actually making a file named tcpserver. So if you keep rerunning make, it'll keep rebuilding tcpserver since the file all will continue to not exist. Change the target to match the actual target. And this is where your linker flags go:
tcpserver : main.o tcpserver.o
g++ -std=c++11 -o tcpserver $^ -lpthread
Additionally, the include guard you're using (__TCP_SERVER_HPP_INCLUDED__) is a reserved name for the C++ standard library. Any name which contains a double underscore or starts with an underscore followed by a capital letter should not be used in your code.
As stated before, this is a compilation problem, with -lpthread at the wrong place.
I recommand using a simpler Makefile, taking advantage of default rules, dependancies, etc. and also setting all sorts of warnings
CXXFLAGS = -std=c++11 -Wall -Wextra -pedantic
LDFLAGS = -lpthread
tcpserver: main.o tcpserver.o
$(LINK.cc) $^ -o $#
clean:
rm -f tcpserver.o main.o tcpserver
# DO NOT DELETE
main.o: tcpserver.hpp
tcpserver.o: tcpserver.hpp
Note: the last 4 lines (starting with DO NOT DELETE) about dependancies were automagically added to the Makefile by the command
makedepend -Y *.cpp
These warnings will be helpful to fix errors:
tcpserver.cpp: In static member function ‘static int Server::parseCmd(const char*, char*)’:
tcpserver.cpp:14:1: warning: no return statement in function returning non-void [-Wreturn-type]
}
^
tcpserver.cpp: At global scope:
tcpserver.cpp:12:34: warning: unused parameter ‘cmd’ [-Wunused-parameter]
int Server::parseCmd(const char *cmd, char *reply) {
^
tcpserver.cpp:12:45: warning: unused parameter ‘reply’ [-Wunused-parameter]
int Server::parseCmd(const char *cmd, char *reply) {
^
tcpserver.cpp:17:47: warning: unused parameter ‘src’ [-Wunused-parameter]
int Server::copystring(char *dst, const char *src) {
^
tcpserver.cpp: In static member function ‘static void* Server::tcp_server(void*)’:
tcpserver.cpp:29:17: warning: unused variable ‘port’ [-Wunused-variable]
const char *port = "5555";
^
tcpserver.cpp:31:1: warning: no return statement in function returning non-void [-Wreturn-type]
}
^
tcpserver.cpp: At global scope:
tcpserver.cpp:28:33: warning: unused parameter ‘dummy’ [-Wunused-parameter]
void *Server::tcp_server(void * dummy) {
I've created a source file that contains a number of data structures (maps, vector, array). Its header file is #included in the main-file.
The main file looks like this:
#include "reachability.h" //Where monkey() and vector<int> int_req are declared
main()
{
monkey(int_req); // Calling monkey(int_req) here is OK! Bar is visible
...
ifstream fp("foo.txt");
if(fp.is_open())
{
std::string line;
while( getline(fp,line) )
{
monkey(int_req); //'int_req' is an undefined reference!
}
}
}
And reachability.h
#ifndef REACHABILITY_H
#define REACHABILITY_H
extern std::vector<int> int_req;
void monkey(std::vector<int> feces);
#endif
And reachability.cc
std::vector<int> int_req;
void monkey(std::vector<int> thrown_obj)
{
... //Iteration and dereferencing of "thrown_obj"
}
I've accessed data structures that are declared in reachability.cc in a for-loop in the scope of main and that was fine. Something wonky is happening in this if-statement though.
Compiler Error:
lab1.o: In function `main':
/home/ubuntu/workspace/ECE597/Lab1/lab1.cc:105: undefined reference to `int_req'
collect2: error: ld returned 1 exit status
Edited: reachability.cc is included in compiliation:
elusivetau:~/XXXX/XXXX/XXXX $ g++ lab1.cc parser.cc gate.cc reachability.cc -o run
/tmp/ccJK4O9q.o: In function `main':
lab1.cc:(.text+0x489): undefined reference to `int_req'
collect2: error: ld returned 1 exit status
Edited: makefile for this program:
all: lab1.o parser.o gate.o reachability.o
g++ -g lab1.o parser.o gate.o reachability.o -o run
lab1.o: lab1.cc
g++ -g -c lab1.cc
parser.o: parser.cc
g++ -g -c parser.cc
gate.o: gate.cc
g++ -g -c gate.cc
reachability.o: reachability.cc
g++ -g -c reachability.cc
clean:
rm *o run
Whatever it is, you're not giving us the correct information.
I added includes and removed non-code to make this compile. And voila, it also links:
test.cpp:
#include "reachability.h" //Where monkey() and vector<int> int_req are declared
#include <string>
#include <iostream>
#include <fstream>
main()
{
monkey(int_req); // Calling monkey(int_req) here is OK! Bar is visible
std::ifstream fp("foo.txt");
if(fp.is_open())
{
std::string line;
while( getline(fp,line) )
{
monkey(int_req); //'int_req' is an undefined reference!
}
}
}
reachability.h:
#ifndef REACHABILITY_H
#define REACHABILITY_H
#include <vector>
extern std::vector<int> int_req;
void monkey(std::vector<int> feces);
#endif
reachability.cpp:
#include "reachability.h"
std::vector<int> int_req;
void monkey(std::vector<int> thrown_obj)
{
}
This compiles and links just fine. You are leading us on a wild goose chase by not bothering to create a mvce
This question already has answers here:
creating classes link error
(2 answers)
Closed 8 years ago.
I'm trying to learn how to make classes in C++ where I use a header file, a .cpp file that contains the class function definitions, and a main .cpp file. Here is what I have (taken from an example)
in class.h
class MyClass
{
public:
void foo();
int bar;
};
in class.cpp
#include "class.h"
using namespace std;
void MyClass::foo()
{
cout<< "test";
}
in main.cpp
#include "class.h"
using namespace std;
int main()
{
MyClass a;
a.foo();
return 0;
}
Compiling the main.cpp results in this error:
[Linker error] C:\:(.text+0x16): undefined reference to `MyClass::foo()'
collect2: ld returned 1 exit status
Do I need to compile the class.cpp or class.h? Am I missing a way of linking class.h with class.cpp? If so how do I link them?
You need to compile the implementation files into object files and link them together. The following is an example for when you are using g++:
g++ -c class.cpp -o class.o
g++ -c main.cpp -o main.o
g++ class.o main.o -o main
./main
In reality, you would add more options like -std=c++11 -O3 -Wall -Wextra -Werror etc.
You can try this on Linux shell using g++
Compile Create object files of main.cpp and class.cpp called main.o and class.o
g++ -c class.cpp
g++ -c main.cpp
Linking the object codes main.o and class.o to create executable file called program
g++ -o program main.o class.o
then run the program executable file
./program
You are likely to be compiling only main.cpp and not class.cpp.
What command are you using to generate the output ?
This should work fine :
g++ class.cpp main.cpp -o class
Its working fine
I tried the code in my Compiler
MyClass.h
#include <iostream>
class MyClass
{
public:
void foo();
int bar;
};
MyClass.cpp
#include "MyClass.h"
using namespace std;
void MyClass::foo()
{
cout<< "test";
}
Main.cpp
#include <iostream>
#include "MyClass.h"
int main(int argc, const char * argv[])
{
MyClass a;
a.foo();
return 0;
}
Ive tried the code in Xcode.
Its working just fine.
Use compiler option -I<dir of .h file> while compiling .cpp file. Compile both the .cpp files
I cannot get this simple piece of code to compile without including the TestClass.cpp file explicitly in my main.cpp file. What am I doing wrong? Thanks in advance!
Here is the code:
TestClass.h
#ifndef TESTCLASS_H_
#define TESTCLASS_H_
class TestClass
{
public:
static int foo();
};
#endif
TestClass.cpp
#include "TestClass.h"
int TestClass::foo() { return 42; }
main.cpp
#include <iostream>
#include "TestClass.h"
using namespace std;
int main()
{
cout << TestClass::foo() << endl;
return 0;
}
Here is the error:
g++ main.cpp -o main.app
/tmp/ccCjOhpy.o: In function `main':
main.cpp:(.text+0x18e): undefined reference to `TestClass::foo()'
collect2: ld returned 1 exit status
Include TestClass.cpp into the commandline, so the linker can find the function definition:
g++ main.cpp TestClass.cpp -o main.app
Alternatively, compile each to their own object file, then tell the compiler to link them together (it will forward them to the linker)
g++ -c main.cpp -o main.o
g++ -c TestClass.cpp -o TestClass.o
g++ main.o TestClass.o -o main.app
You're not compiling and linking against TestClass.cpp (where the implementation of foo() is). The compiler is thus complaining that your trying to use an undefined function.