Issues with compiling multiple files - c++

So I'm trying to write a bit of code to work with sudoku puzzles, and I keep getting errors when I try to compile, and each time i compile it deletes the driver.
heres the code for the driver:
/*
* Jared C
* C++ Project
*/
#include <iostream>
#include "SudokuBoard.h"
using namespace std;
int main()
{
SudokuBoard board("sudoku.txt");
board.printBoard();
}
And here's the header file
/*
* Jared C
* SudokuBoard.h
*/
#ifndef __SUDOKUBOARD_H_INCLUDED__
#define __SUDOKUBOARD_H_INCLUDED__
#include <iostream>
#include <string>
class SudokuBoard
{
private:
int content[9][9];
public:
SudokuBoard(std::string filename);
void printBoard();
int getNumAt(int, int);
void setNumAt(int, int, int);
};
#endif
And finally the Sudoku Board.cpp
/*
* Jared C
* SudokuBoard.cpp
*/
#include <iostream>
#include <fstream>
#include "stdlib.h"
#include "SudokuBoard.h"
using namespace std;
SudokuBoard::SudokuBoard(string filename)
{
string output;
string line;
int count = 0;
ifstream file;
file.open(filename.c_str());
if (file.is_open())
{
while (getline (file, line))
{
output += line;
}
file.close();
}
else cout<< "unable to open file" << endl;
for(int y = 0; y < 9; y++)
{
for(int x = 0; x < 9; x++)
{
content[x][y] = atoi(output.substr(count,1).c_str());
count ++;
}
}
}
void SudokuBoard::printBoard()
{
string output = "\n";
for(int y = 0; y < 9; y++)
{
if(y%3==0)
{
output += '\n';
}
for(int x = 0; x < 9; x++)
{
if(x%3==0)
{
output += " ";
}
output += content[x][y];
output += "\n";
}
}
cout<<output<<endl;
}
int SudokuBoard::getNumAt(int x, int y)
{
return content[x][y];
}
void SudokuBoard::setNumAt(int x, int y, int value)
{
content[x][y] = value;
}
When i call gcc -c SudokuBoard.cpp I get the SudokuBoard.o file just fine, but when I then call 'gcc -o Driver.cpp SudokuBoard.o' I get a huge wall of error messages, heres a sample of them:
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 11
SudokuBoard.cpp:(.text+0x34): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string()'
SudokuBoard.cpp:(.text+0x43): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string()'
And it deletes Driver.cpp Any idea what I'm doing wrong?

Your command line is incorrect:
gcc -o Driver.cpp SudokuBoard.o
Instructs gcc to link the object file SudokuBoard.o as an executable file named Driver.cpp. No surprise that it first erases the destination file.
Furthermore, you do not specify the runtime library to link with and gcc does not default to C++: this explains the error message.
You should instead write:
g++ -o Sudoku Driver.o SudokuBoard.o

Use g++ to compile C++ code, not the common C-oriented gcc.
g++ invokes gcc for compilation and linking with the right options for C++.
In short, it's a good idea to use a C++ compiler for C++ source code, a Fortran compiler for Fortran source code, and so on.
Also, for the issue of “And it deletes Driver.cpp”, simply don't specify that source file as an output file.

The problem is that the -o option with gcc is used for specifying the output file. If you write
gcc -o Driver.cpp SudokuBoard.o
you tell the compiler to create an executable file named Driver.cpp out of the object file SudokuBoard.o. But as SudokuBoard.o has no main method, this will fail, therefore the error messages.
Try
gcc -c SudokuBoard.cpp
gcc -c Driver.cpp
gcc -o Sudoku SudokuBoard.o Driver.o
instead.

The compiler is telling you it can't find the implementation for std::basic_string<...>.
You need to tell the compiler how to find the compiled code for std::basic_string<...>. Much how with your own code, if you tried to build an executable out of just Driver.cpp the compiler would complain about missing SudokuBoard references until you told it about SudokuBoard.o.
In this case you need to tell the compiler about the C++ standard library. This library are usually shipped with your distribution. On Windows in the form of dll files, on OS X dylib files and on Linux so files. Conceptually they are similar, many bags of .o files all together. Either way, you tell the linker to link to the C++ standard library.
gcc calls the C++ standard library libstdc++, so your command would be something like: gcc -o Driver Driver.cpp SudokuBoard.o -lstdc++.

Related

C++ linker error despite using g++, clang etc to compile

I'll start by showing you the error I have been getting:
Henrys-MacBook-Pro-2:assignment1 HenryDashwood$ clang++ main.cpp
Undefined symbols for architecture x86_64:
"clear()", referenced from:
_main in main-a61991.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've been trying to move some functions into a source.cpp file with prototypes in a header.h file. The code works fine when I have it all in the main.cpp file. It also works when I move the function prototype to a header file. However, when I then also move the functions to the source file, it errors me! Here are the relevant bits of my code:
main.cpp
#include <string>
#include <iostream>
using namespace std;
#include "header.h"
int main()
{
char quit, choice;
int term, day, hour;
string termName, dayName;
clear();
return 0;
}
header.h
#define TERMS 4
#define DAYS 7
#define HOURS 8
struct TTcell
{
string subject;
string lecturer;
string roomName;
};
struct TTcell timetables[8][7][4];
void clear();
source.cpp
#include <string>
#include <iostream>
using namespace std;
#include "header.h"
void clear()
{
for (size_t i = 0; i < TERMS; i++) {
for (size_t j = 1; j <= DAYS; j++) {
for (size_t k = 1; k <= HOURS; k++) {
timetables[k][j][i].subject = "";
timetables[k][j][i].lecturer = "";
timetables[k][j][i].roomName = "";
}
}
}
}
This is an example using one function to keep the question readable. They all seem to have the same affliction. I saw on other posts people got similar errors because of the compiler they were using. I've tried c++, g++ and clang++, all to no avail.
Thank you in advance for any ideas you come up with!
You have two options to make this compile.
Compile all the cpp files on one line
g++ main.cpp source.cpp -o main
Compile separately and link
g++ -c main.cpp
g++ -c source.cpp
g++ -o main main.o source.o
This is a bog-standard failure to bring in your source files, and has nothing to do with your compiler.
Henrys-MacBook-Pro-2:assignment1 HenryDashwood$ clang++ main.cpp
You didn't build & link source.cpp.
So, as far as Clang knows, the definition for clear() indeed does not exist.
Henrys-MacBook-Pro-2:assignment1 HenryDashwood$ clang++ main.cpp source.cpp

How to link boost properly? [duplicate]

I'm writing a program to get myself acquainted with OpenSSL, libncurses, and UDP networking. I decided to work with OpenSSL's SHA256 to become familiar with industry encryption standards, but I'm having issues with getting it working. I've isolated the error to the linking of OpenSSL with the compiled program. I'm working on Ubuntu 12.10, 64 bit. I have the package libssl-dev installed.
Take, for instance, the C++ main.cpp:
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
using namespace std;
#include <openssl/sha.h>
string sha256(const string str)
{
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, str.c_str(), str.size());
SHA256_Final(hash, &sha256);
stringstream ss;
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
ss << hex << setw(2) << setfill('0') << (int)hash[i];
}
return ss.str();
}
int main()
{
cout << sha256("test") << endl;
cout << sha256("test2") << endl;
return 0;
}
I'm using the SHA256() function found here as a wrapper for OpenSSL's SHA256 functionality.
When I attempt to compile with the following g++ arguments, I receive the following error:
millinon#myhost:~/Programming/sha256$ g++ -lssl -lcrypto -o main main.cpp
/tmp/ccYqwPUC.o: In function `sha256(std::string)':
main.cpp:(.text+0x38): undefined reference to `SHA256_Init'
main.cpp:(.text+0x71): undefined reference to `SHA256_Update'
main.cpp:(.text+0x87): undefined reference to `SHA256_Final'
collect2: error: ld returned 1 exit status
So, GCC clearly recognizes OpenSSL's defined functions and types, but ld is failing to find the function symbols referred to in sha.h.
Do I need to manually point to a specific shared object or directory?
Thanks!
You make a very common beginners mistake... Putting the libraries you link with in the wrong place on the command line when you build.
Dependencies are reversed on the command line, so something that depends on something else should actually be put before what it depends on on the command line.
In your example, you have a source file main.cpp that depends on some set of libraries, then the source file should be before the libraries it depend on:
$ g++ -o main main.cpp -lssl -lcrypto
To be safe, always put libraries last, after any source or object files listed on the command line.
This works fine on my system, but you might try:
extern "C" {
#include <openssl/sha.h>
}
which tells g++ that all the stuff in openssl/sha.h is declared as "C" functions.
BTW, how old is your OpenSSL?

dlopen() gives unresolved symbol error when .so tries to use a class from the main executable. Why?

I'm on Linux, the question is concerning shared objects of C++ classes.
The problem comes when my shared objects try to use resources linked into the main executable. I have the following codes:
loader.cpp:
#include <dlfcn.h>
#include <iostream>
#include "CommonInfo.h"
using namespace std;
int main(int argc, char** argv) {
for(int i=1; i<argc; ++i) {
string pth = "./";
pth.append(argv[i]);
void* dh = dlopen(pth.c_str(), RTLD_NOW);
if(dh==NULL) {
cerr << dlerror() << endl;
return 1;
}
CommonInfo::GetInfoFunc getInfo = (CommonInfo::GetInfoFunc)(dlsym(dh,"getInfo"));
if(getInfo==NULL) {
cerr << dlerror() << endl;
return 1;
}
CommonInfo* info = getInfo();
cout << "INFO: " << info->getX() << endl;
delete info;
}
return 0;
}
CommonInfo.h:
#include <string>
class CommonInfo {
public:
typedef CommonInfo* (*GetInfoFunc)();
private:
std::string x;
public:
CommonInfo(const std::string& nx);
std::string getX() const;
};
EDIT:
I accidentaly forgot to ctrl-c + ctrl-v the source of CommonInfo.cpp here. Of course, it is there during compilation, so CommonInfo.cpp:
#include "CommonInfo.h"
CommonInfo::CommonInfo(const std::string& nx) : x(nx) {
}
std::string CommonInfo::getX() const {
return x;
}
A Plugin.h header:
#include "CommonInfo.h"
extern "C" CommonInfo* getInfo();
A very simple Plugin.cpp:
#include <iostream>
#include "Plugin.h"
#include "CommonInfo.h"
using namespace std;
CommonInfo* getInfo() {
return new CommonInfo("I'm a cat!");
}
Compiling is done with:
g++ -rdynamic -ldl -Werror CommonInfo.cpp loader.cpp -o loader
g++ -shared -fPIC -Werror Plugin.cpp -o Plugin.so
Running:
./loader Plugin.so
And there goes the error:
./loader: symbol lookup error: ./Plugin.so: undefined symbol: _ZN10CommonInfoC1ERKSs
Indeed, looking inside Plugin.so with nm Plugin.so | grep -i CommonInfo it gives an 'U' for this symbol (unresolved), which is perfectly ok.
Also, looking inside the binary of loader with nm loader.so | grep -i CommonInfo I could find the symbol with 'T', which is also ok.
Question is, shouldn't dlfcn.h unresolve the symbol in question from the main binary? Without this feature it becomes quite hard to use these stuff... Do I have to write a class factory function for CommonInfo, load it with dlfcn from the plugin and call that?
Thanks in advance,
Dennis
I haven't looked closely at your code, but I have in the past found behavior like you describe in the title when I did not link the executable with -E. (Or -Wl,-E when linking with gcc rather than ld.)
Note that not all platforms let the shared libraries take symbols from the calling binary. Linux and the *BSDs allow you to. But if you ever want to port to, say, Windows, you will not be able to use this pattern. I believe there are also some Unix-type OS's that won't let you do this. (It's been a while so I don't remember... Maybe it was Solaris?)

I get an "undefined reference to ..." for two of my functions

I have created three separate files. The first is the main.cpp the 2nd is a header file called "statistics.h" which has the declarations for the two functions i am getting the error and the 3nd is a file called statistics.cpp which holds the implementation of the two functions.
Here is my main file:
#include <iostream>
#include "statistics.h"
using namespace std;
int main()
{
cout<<"This program provides the average and the standard deviation of 1,2,3 or 4 numbers."<< endl;
while(true){
start:
unsigned int howmany;
cout<<endl;
cout<<"How many numbers do u wish to receive as input?? ";
cin >> howmany;
if (howmany>4){
cout<<"You should pick at most 4 numbers u idiot!!!"<< endl<<endl;
goto start;
}
if(howmany==0){
return 0;
}
cout<< endl;
double nums[howmany];
for (int i=0;i<howmany;i++){
cout<<"Give me the number "<<i+1<<":";
cin>>nums[i];
}
double avg=average(nums,howmany); /////////////////////////////
double stdev=standard_deviation(nums,howmany,avg); ////////////////////
cout<< endl<<"Average: "<<avg<<". Standard Deviation: "<< stdev<< endl;
}
}
My header file is:
#ifndef STATISTICS_H_INCLUDED
#define STATISTICS_H_INCLUDED
double average(double ar[],int hm);
double standard_deviation(double ar[],int hm,double avrg);
#endif // STATISTICS_H_INCLUDED
And my implementation file statistics.cpp is:
#include<iostream>
#include"statistics.h"
#include <math.h>
using namespace std;
double average(double ar[],int hm){
double sum=0.0;
double average;
for(int i=0;i<hm;i++){
sum+=ar[i];
}
average=sum/hm;
return average;
}
double standard_deviation(double ar[],int hm,double avrg){
double std_dev;
double sum=0;
double ans;
for(int i=0;i<hm;i++){
sum+= ((ar[i]-avrg)*(ar[i]-avrg));
}
ans=sqrt(sum/hm);
return ans;
}
I am getting the errors in my main file (i have marked the corresponding lines with consecutive ////////). What could be wrong?? I am sure its something stupid from my part.
As i am using codeblocks i finally found the solution. I just needed to add #include "statistics.cpp" to my main.cpp file.
You forgot to link statistics.o together with main.o, so your hypothetical executable will not contain the function definitions.
(The hypothetical executable can thus not exist, so you're getting a linker error.)
Variation 1
Where you're writing something like:
g++ main.cpp -o myExecutable
instead write:
g++ main.cpp statistics.cpp -o myExecutable
Variation 2
Where you're writing something like:
g++ -c main.cpp
g++ main.o -o myExecutable
instead write:
g++ -c main.cpp
g++ -c statistics.cpp
g++ main.o statistics.o -o myExecutable
If you're still having trouble, try reversing the order in which you provide the filenames to g++ (though the above should be correct).
Incidentally, you are not allowed to define an array with variable dimensions. Use a std::vector instead.
As i am using codeblocks i finally found the solution. I just needed to add #include "statistics.cpp" to my main.cpp file.
!!! This is NOT a solution. Do not include implementation files. You will fall into a pit of despair, decay and disorganization.
Everything was fine with your use of header files. You just need to tell your IDE to compile both files as a single project. Consult the documentation.

C++ compiling problem; class methods

I have started writing a very simple class, and all kinds of class methods seem to give me problems. I hope the problem is me and the solution is simple.
The command g++ -o main main.cpp gives the folowing output:
/usr/bin/ld: Undefined symbols:
Lexer::ConsoleWriteTokens()
collect2: ld returned 1 exit status
main.cpp:
#include<iostream>
#include"lexer.h"
int main(){
Lexer lexhnd = Lexer();
std::cout << "RAWR\n";
lexhnd.ConsoleWriteTokens();
std::cout << "\n\n";
return 0;
}
lexer.h:
#ifndef __SCRIPTLEXER
#define __SCRIPTLEXER
#include <iostream>
#include <string>
#include <vector>
#define DEF_TOKEN_KEYWORD 0
struct token{
int flag;
std::string data;
};
class Lexer
{
public:
// bool IsTrue();
// bool AddLine(char * line);
void ConsoleWriteTokens(void);
private:
std::vector<token> TOK_list;
};
#endif
lexer.cpp:
bool Lexer::IsTrue(){
return true;
};
bool Lexer::AddLine(char * line){
token cool;
cool.data = line;
TOK_list.push_back(cool);
string = line;
return true;
};
void Lexer::ConsoleWriteTokens(void){
for (int i = 0; i < TOK_list.size(); i++){
std::cout << "TOKEN! " << i;
}
return 0;
};
I am using g++ in xcode btw.
Thankyou very much in advance, I have been on this problem for a few hours.
EDIT:
g++ -o main lexer.h main.cpp
or
g++ -o main lexer.cpp main.cpp
or
g++ -o main main.cpp lexer.cpp
do NOT work either.
-Hyperzap
Your not compiling the lexer.cpp code.
Try
g++ -o main main.cpp lexer.cpp
as your compilation command.
PROBLEMS IN THE lexer.cpp
You probably want to include the lexer header in the lexer.cpp file
#include "lexer.h"
Also, you don't want to return an integer from void functions.
void Lexer::ConsoleWriteTokens(void){
for (int i = 0; i < TOK_list.size(); i++){
std::cout << "TOKEN! " << i;
}
//This function is void - it shouldn't return something
//return 0;
};
Finally, you have some problems withs this function
bool Lexer::AddLine(char * line){
token cool;
cool.data = line;
TOK_list.push_back(cool);
//what is this next line trying to achieve?
//string = line;
return true;
};
I'm not sure what you are trying to achieve with the line I commented out,
it doesn't seem to do anything and string isn't defined (did you mean std::string mystring = line;)
Finally, don't forget to uncomment the functions declaired in lexer.h that you are defining in lexer.cpp.
Include all the .cpp files in the command line, like this:
g++ -o main main.cpp lexer.cpp
When your project grows, it becomes wise to manage your project in some automatic way: Makefiles, ant, or some IDE-integrated project file.
Well g++ -o main main.cpp lexer.cpp sould do the trick. However I suggest making makefile files. When having a multiple amount of file they come in handy.
I would also suggest adding some optimization to your compilation like -O3 or -O2 (O is a letter o not zero digit!). The difference in execution speed is very noticable. Also if you are goig to make libraries out of your files, why not using --shared option that will create a liked library. I find making shared libraries very useful.