Linker error multiple definition of class constructor - c++

solved
I had to delete the old object-files and rebuilt the whole project to fix the problem. Unfortunately I don't know the very reason why I got this error.
Maybe it where some wrong placed include-statements or there may have been definitions in the class declaration of accountsContainer.h which I had removed meanwhile.
I am trying to compile a little C/C++ application and am stuck with a linking problem:
the exact error is this:
make all
g++ -g -Wall -fmessage-length=0 -I "Z:/SRS/Verwaltung/EDV/Marcus EDV/Programmierung/link libraries/c++/curl-7.24.0/include/curl/" -c -o accountsContainer.o accountsContainer.cpp
g++ -o libcurl.exe signatureUpdater.o accountsContainer.o network.o registry.o emailAccount.o filesystem.o libcurl.o "Z:/SRS/Verwaltung/EDV/Marcus EDV/Programmierung/link libraries/c++/curl-7.24.0/lib/libcurl.dll"
accountsContainer.o: In function `accountsContainer':
G:\#1Arbeit\htdocs\libcurl/accountsContainer.cpp:11: multiple definition of `accountsContainer::accountsContainer()'
signatureUpdater.o:G:\#1Arbeit\htdocs\libcurl/accountsContainer.h:13: first defined here
collect2: ld returned 1 exit status
make: *** [libcurl.exe] Error 1
I don't understand where this error comes from. I already did some research on the internet for the "multiple definition of"-error.
This is what I know:
I think you can declare classes or functions several times as often as you want, but I must only be defined once.
And this is what I did:
I defined the class constructor "accountsContainer::accountsContainer(){...}" in the accountsContainer.cpp which is never included anywhere, but should only be compiled with my make-file to accountsContainer.o
accountsContainer.h contains the declaration of the class
But why does the linker complain about a definition of accountsContainer::accountsContainer(){...} in the header file?
These are my files:
"accountsContainer.h"
/*
* accountsContainer.h
*
* Created on: 16.03.2012
* Author: Admin
*/
#ifndef ACCOUNTSCONTAINER_H_
#define ACCOUNTSCONTAINER_H_
#include "emailAccount.h"
#include <string>
#include <iostream>
#include <algorithm>
class accountsContainer {
public:
const static int MAX_ACCOUNTS = 50;
private:
emailAccount srsAccounts[],emailAccounts[];
//can only be initalized in the constructor
int nAccounts;
int nSrsAccounts;
//methods
private:
void emailToLowerCase();
void findSrsAccounts();
public:
accountsContainer();
void printSrsAccounts();
emailAccount & getSrsAccount(int);
};
#endif /* ACCOUNTSCONTAINER_H_ */
"accountsContainer.cpp"
/*
* accountsContainer.cpp
*
* Created on: 16.03.2012
* Author: Admin
*/
#include "accountsContainer.h"
#include "signatureUpdater.h"
accountsContainer::accountsContainer() {
//init variables
nAccounts = 0;
nSrsAccounts = 0;
/*
* read email Accounts from registry and save them to the srsAccounts Array
*/
signatureUpdater::reg.getEmailAccounts(srsAccounts,MAX_ACCOUNTS);
//make all e-mail adresses lower case
emailToLowerCase();
findSrsAccounts();
}
void accountsContainer::printSrsAccounts(){
string locS;
for(int i=0;i < nSrsAccounts;i++){
wcout << L"Account " << i << L" : " << srsAccounts[i].displayName <<endl;
wcout << L"Name: " << srsAccounts[i].accName.c_str() << endl;
wcout << L"E-Mail:" << srsAccounts[i].email.c_str() << endl << endl;
}
}
emailAccount & accountsContainer::getSrsAccount(int i){
return srsAccounts[i];
}
void accountsContainer::emailToLowerCase(){
wstring s;
for(int i=0; i < nAccounts; i++){
s = emailAccounts[i].email;
std::transform(s.begin(), s.end(), s.begin(), std::ptr_fun<int,int>(std::tolower));
emailAccounts[i].email = s;
}
}
void accountsContainer::findSrsAccounts(){
/*
* resets Number of SRS accounts
* then iterates all e-mail accounts
* and searches for domain srsonline.de
* in lowercase!
*/
size_t found;
wstring emailAdr;
nSrsAccounts = 0;
for(int i=0;i<nAccounts;i++){
emailAdr=emailAccounts[i].email;
found = emailAdr.rfind(L"srsonline.de");
if(found != string::npos && (emailAdr.length()-found) == 12){
/*
wcout << L"für E-mail Konto: " << emailAdr << endl;
cout << "srsonline.de found at: " << found << endl;
*/
// copy SRS Accounts to srsAccounts array
srsAccounts[nSrsAccounts] = emailAccounts[i];
nSrsAccounts++;
}
}
}
and thats my makefile:
CXXFLAGS = -g -Wall -fmessage-length=0 -I "Z:/SRS/Verwaltung/EDV/Marcus EDV/Programmierung/link libraries/c++/curl-7.24.0/include/curl/" # -O2 no performance improvement because of debugging!
OBJS = signatureUpdater.o accountsContainer.o network.o registry.o emailAccount.o filesystem.o libcurl.o
LIBS = "Z:/SRS/Verwaltung/EDV/Marcus EDV/Programmierung/link libraries/c++/curl-7.24.0/lib/libcurl.dll"
TARGET = libcurl.exe
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
I hope that the problem doesn't come from a bad programm-architectur/design
thank you for your help!

Check the include guards, maybe you use the same name in another header.

Related

Unused variable warning even when explicitly using it inside IF statement

I am trying to create (using C++17) a simple debug header that only executes some lines of code if the flag LOGGER_DEBUG_MODE is enabled. This is how my header is defined (I also tried using { x; } instead of x but the warning persists):
debug.h
#ifndef _HDEBUG
#define _HDEBUG
static bool LOGGER_DEBUG_MODE = true;
#define R_DEBUG(x) if(LOGGER_DEBUG_MODE == true) x
#endif
I included debug.h and at some point of my code I call the macro function R_DEBUG to print some values:
logger_adc.cpp
double anlg_device_t::eval_formula()
{
double result = -9999;
try
{
result = parser.Eval();
}
catch (mu::Parser::exception_type &e)
{
std::cout << e.GetMsg() << std::endl;
}
R_DEBUG(std::cout << "Eval Result: " << result << std::endl);
return result;
}
I expected everything to work properly but when I run the makefile I got this warning:
inc/debug.h:5:14: warning: 'LOGGER_DEBUG_MODE' defined but not used [-Wunused-variable]
static bool LOGGER_DEBUG_MODE = true;
I thought that my definition was messed up but after checking the temporary files created by g++, it appears that the preprocessor did everything as I expected:
logger_adc.ii
double anlg_device_t::eval_formula()
{
double result = -9999;
try
{
result = parser.Eval();
}
catch (mu::Parser::exception_type &e)
{
std::cout << e.GetMsg() << std::endl;
}
if(LOGGER_DEBUG_MODE == true) std::cout << "Eval Result: " << result << std::endl;
return result;
}
Why do I get the warning message even when the variable LOGGER_DEBUG_MODE is clearly being used inside the if statement? Did I mess up something obvious that I'm not picking up? My compile flags for the object files (where the warning occurs) are g++ -Wall -Wextra -O1 -g -std=c++17 -save-temps=obj -Iinc -I/usr/local/include -c plus pkg-config --cflags --libs libmodbus
If needed, this is my main function:
main.cpp
#include "logger_adc.h"
int main()
{
anlg_device_t test (ADC_CHIP_1, 1, 18, 1, 1, true);
test.set_formula("2*x","x", test.get_voltage_ptr());
std::cout << "Test Voltage: " << test.get_voltage() << std::endl << "Test Relative: " << test.get_relative() << std::endl;
std::cout << "Test Formula (2*x): " << test.eval_formula() << std::endl;
return 0;
}
Thanks in advance!
You have a header that defines a static bool LOGGER_DEBUG_MODE =true;. If you include that header in multiple C++ files then each file will gets its own copy of that bool.
In your main.cpp you aren't using R_DEBUG so the copy of that bool (which presumably comes from including logger_adc.h ) is indeed unused in that file.
Possible solutions are:
You should make it so you only have a single copy of that bool (declare it in the header with extern and define it in a single C++ file.
Use build defines instead of runtime checks
etc

no member named 'array' in namespace 'std'

I am learning C++ right now and i get this somewhat weird error.
The Code is as follows:
#include <iostream>
#include <array>
using std::cout;
using std::endl;
using std::ostream;
using std::array;
template <typename T, size_t dim>
ostream& operator<<(ostream& os, const array<T,dim>& a) {
os << "[ ";
for (auto n : a)
os << n << " ";
os << "]";
return os;
}
int main()
{
cout << endl << "--- " << __FILE__ << " ---" << endl << endl;
array<int,3> a1 { 2,3,5 }; // (A)
array<int,0> a2 { }; // (B)
array<int,2> a3 { 1 }; // (C)
// array<int> x1 { 1, 2, 3 }; // (D)
// array<int,3> x2 { 1,2,3,4 };
array<int,3> a4 = { 1,2,3 }; // (E)
array<int,3> a5 { { 4,5,6 } }; // (F)
cout << "01| a1=" << a1 << endl;
cout << "02| a2=" << a2 << endl;
cout << "03| a3=" << a3 << endl;
cout << "04| a4=" << a4 << endl;
cout << "05| a5=" << a5 << endl;
cout << endl << "--- " << __FILE__ << " ---" << endl << endl;
return 0;
}
My IDE (Visual Studio Code) shows me the error, although the code is compiling and working.
Here is the makefile provided by our Prof.
# compiler settings
CXX = g++-7
# CXX = clang++
CXXFLAGS = -ansi -pedantic -Wall -Wextra -Wconversion -pthread -std=c++17
LDFLAGS = -lm
# collect files
CXXEXAMPLES = $(shell find . -name '*.cpp' -print -type f)
CXXTARGETS = $(foreach file, $(CXXEXAMPLES), ./out/$(file:.cpp=.out))
# build them all
all: $(CXXTARGETS)
out/%.out: %.cpp
$(CXX) $(CXXFLAGS) $< $(LDFLAGS) -o $#
clean:
rm out/*
I use Ubuntu 16.04 and thought it might be a compiler problem, so I changed "CXX" to "CXX = g++-7", because we were recommended to use g++ Version 7 but it didn't helped.
On typing "g++ -v" it shows that my gcc is version 5.5.0, but typing "apt list -installed" shows that g++-7 is installed.
I did not find any solution on the internet as most similar problems often revolved around missing includes.
VS Code also does not recognize some types of variable definitions like
"int n{1}"
It also complains about the "use of undeclared identifier" on the lines (A) to (E)
I assume the problem lies within the VS Code compiler using a different/old syntax recognition. But I don't know how to change that.

C++ Getting undefined symbol error

I am trying to do an assignment and the program compiles fine on my home
PC (Netbeans) but when I try and compile on the Uni Sun box I get the following error
compile flags : g++ -lm -ansi -Wall -pedantic skyhigh.cpp -o skyhigh
Undefined first referenced
symbol in file
Flight::GetSeats() /var/tmp//cc49OAwj.o
Flight::GetCost() /var/tmp//cc49OAwj.o
Flight::GetAircraft() /var/tmp//cc49OAwj.o
ld: fatal: Symbol referencing errors. No output written to skyhigh
collect2: ld returned 1 exit status
Any help would be greatly appreciated,as I have spent hours combing the internet
for the solution
FLIGHT.H File
//
// flight.h
//
// Parent Flight class
//
#ifndef __FLIGHT_H__
#define __FLIGHT_H__
#include<iostream>
#include<string>
using namespace std;
/*TO DO REQUIRED HEADER FILES AND NAMESPACES*/
class Flight
{
protected:
string aircraft;
string category;
int seats;
double cost;
public:
virtual ~Flight(){};
// virtual void Display() =0;
void SetAircraftType(string air);
string GetAircraft();
int GetSeats();
double GetCost();
void SetSeats(int seat);
//TO DO
// Prototypes of all the Item functions
};
#endif
FLIGHT.CPP FILE
#include "flight.h"
string Flight::GetAircraft(){
return aircraft;
}
int Flight::GetSeats(){
return seats;
}
double Flight::GetCost(){
return cost;
}
void Flight::SetSeats(int seat){
seats=seat;
}
void Flight::SetAircraftType(string category){
aircraft = category;
}
MAIN FILE
// skyhigh.cpp for CPT 323 Assignment 1 SP3 2013
//
//
// CPT323 2013 assignment 1
#include "skyhigh.h"
/////////////////////////////////////////////////////
int main()
{
Flight newflight ;
cout<< "Plane Name:" <<newflight.GetAircraft()<< " Seats: "<< newflight.GetSeats()<<"Cost: "<<newflight.GetCost()<< endl;
Scenic newflight2 ;
//cout<< "Plane Name:" <<newflight2.GetAircraft()<< " Seats: "<< newflight2.GetSeats()<<"Cost: "<<newflight2.GetCost()<< endl;
//Scenic* sptr=&newflight2;
//BookingSheet booking;
//cout<< booking.GetDay()<<booking.GetTime()<<booking.GetPassengerName()<<booking.GetPaymentStatus()<<endl;
int finished = 0;
do {
/*Create array for use in menu options*/
cout << "Main Menu : " <<endl;
cout << "1) Add a flight booking "<<endl;
cout << "2) Remove a flight booking "<<endl;
cout << "3) View current booking sheet " <<endl;
cout << "0) Exit \n" <<endl;
cout<< "Please make a selection (0-3) ";
int selection;
cin>> selection;
/*Capture user selection default in switch statement validates 1-9*/
// fgets(option,sizeof(option),stdin);
//
//
switch (selection) {
case 0:
cout << "Thanks for using the SkyHigh Booking System"<<endl;
finished=1;
break;
case 1:
cout << "1) Add a flight booking "<<endl;
break;
case 2:
cout << "2) Add Customer "<<endl;
break;
case 3:
cout << "3) Display Stock " <<endl;
break;
default:
printf("Valid input is 0-3 \n");
}
}
while(!finished);
return 0;
}
MakeFile
skyhigh: skyhigh.o utility1.o flight.o scenic.o aerobatic.o
g++ skyhigh.o utility1.o flight.o scenic.o aerobatic.o -o skyhigh
skyhigh.o: skyhigh.cpp skyhigh.h flight.h aerobatic.h scenic.h
g++ -ansi -Wall -pedantic -gstabs -c skyhigh.cpp
utility1.o: utility1.cpp utility1.h
g++ -ansi -Wall -pedantic -gstabs -c utility1.cpp
flight.o: flight.cpp flight.h aerobatic.h scenic.h
g++ -ansi -Wall -pedantic -gstabs -c flight.cpp
scenic.o: scenic.cpp scenic.h
g++ -ansi -Wall -pedantic -gstabs -c scenic.cpp
aerobatic.o: aerobatic.cpp aerobatic.h
g++ -ansi -Wall -pedantic -gstabs -c aerobatic.cpp
clean:
rm -f *.o core *.report *.errs
It can't find the object file where those missing functions are defined. Make sure you are adding the generated object file for linking. Something like that (main is the exec name and main.o is the object with the main function, change them as needed):
g++ -o main main.o skyhigh.o utility1.o flight.o scenic.o aerobatic.o

How to add an external library in c++ using Cygwin

I've already wasted time trying to figure this out but no luck so far...I've tried looking through StackOverflow for the same problem but mostly it's related to the IDE people are using, such as VS or Eclipse.
I was doing some examples from the Stanford Reader for their C++ course but the code won't work right. I'm trying to figure out how to use external libraries but something keeps going wrong. I'm probably not using the right command but then I don't know which command to use.
I'm using Cygwin and it's terminal to do the c++ exercises. I have all the files in the same folder. I am using windows 7 but that shouldn't be the biggest problem though.
As an example this error shows well what I get when writing g++ Craps.cpp:
$ g++ Craps.cpp
/tmp/ccdTdi0t.o:Craps.cpp:(.text+0x1cf): undefined reference to `randomInteger(int, int)'
/tmp/ccdTdi0t.o:Craps.cpp:(.text+0x1e6): undefined reference to `randomInteger(int, int)'
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../../i686-pc-cygwin/bin/ld: /tmp/ccdTdi0t.o: bad
reloc address 0x0 in section `.ctors'
collect2: ld returned 1 exit status
The example I was running this time is just one of the ones with external libraries which gives me the same kind of error if I wrong the other. It won't find the library.
This is my main also called Craps.cpp:
#include <iostream>
#include "random.h"
using namespace std;
bool tryToMakePoint(int point);
int rollTwoDice();
int main() {
cout << "This program plays a game of craps." << endl;
int point = rollTwoDice();
switch (point) {
case 7: case 11:
cout << "That's a natural. You win." << endl;
break;
case 2: case 3: case 12:
cout << "That's craps. You lose" << endl;
break;
default:
cout << "Your point is " << point << "." << endl;
if (tryToMakePoint(point)) {
cout << "You made your point. You win." << endl;
} else {
cout << "You rolled a seven. You lose." << endl;
}
}
return 0;
}
bool tryToMakePoint(int point) {
while (true) {
int total = rollTwoDice();
if (total == point) return true;
if (total == 7) return false;
}
}
int rollTwoDice() {
cout << "Rolling the dice . . . " << endl;
int d1 = randomInteger(1, 6);
int d2 = randomInteger(1, 6);
int total = d1 + d2;
cout << "You rolled " << d1 << " and " << d2
<< " - that's " << total << endl;
return total;
}
My random.cpp:
#include <cstdlib>
#include <cmath>
#include <ctime>
#include "random.h"
using namespace std;
void initRandomSeed();
int randomInteger(int low, int high) {
initRandomSeed();
double d = rand() / (double(RAND_MAX) + 1);
double s = d * (double(high) - low + 1);
return int(floor(low + s ));
}
double randomReal(double low, double high) {
initRandomSeed();
double d = rand() / (double(RAND_MAX) + 1);
double s = d * (high - low);
return low + s;
}
bool randomChance(double p) {
initRandomSeed();
return randomReal(0, 1) < p;
}
void setRandomSeed(int seed) {
initRandomSeed();
srand(seed);
}
void initRandomSeed() {
static bool initialized = false;
if (!initialized) {
srand(int(time(NULL)));
initialized = true;
}
}
and lastly my random.h:
#ifndef _random_h
#define _random_h
int randomInteger(int low, int high);
double randomReal(double low, double high);
bool randomChance(double p);
void setRandomSeed(int seed);
#endif
I hope someone can help me. If it's the Cygwin command that's wrong it would be great if I could see what I should write.
Edit:
Just found out that I couldn't even write down the examples in the book right. Fixed now and should be without mistakes...I dearly hope so. Sorry about that.
Shortly, you should add random.cpp (or, if you already compiled it, an object file or a library where its compiled code resides) into your command line:
g++ Craps.cpp random.cpp
The problem you face is that the command line says the code in Craps.cpp should be compiled and then linked into an executable. While it's sufficient to have forward declarations of external functions to compile the file, you should provide the code of these functions to the linker for it to be able to create an executable.
As for libraries, you usually specify ones that you need to use with -l option to GCC. And you might need to specify (with -L) the path where to take libraries from, even if they all are in the current directory. E.g. provided that you have a library called librandom.a or librandom.so in the current directory:
g++ Craps.cpp -L. -l random
For external libraries, other directories may need to be specified so that the linker knows where to find the libraries it needs.
Other answer has the simple command to compile this, but here's a very rough and simple Makefile example, to get you started down that road. Create a file named Makefile with these contents, where <tab> must be an actual tab character, not some number of spaces:
Craps.exe : Craps.o random.o
<tab>g++ -o $# $^
Craps.o random.o : random.h
Then just run
make Craps.exe
(possibly gmake or mingw32-make instead of plain make).
Now Make has some magic built in about file types, so when it sees Craps.exe needs those two .o files, it'll start looking for files it could make them from, and it finds .cpp files, and knows how to compile them into .o files. Now it doesn't implicitly know how make .exe out of .o files, so that's why we have the 2nd line. There $# means the target of the rule (Craps.exe here), while $^ means all the files listed after the :.
The Craps.o random.o:random.h rule means, that if random.h is changed, Craps.o and random.o needs to be re-created again (these .h file dependencies can be generated automatically, but as long as you have just a few files, writing them by hand is ok).
If you need to add more source files, just add them with the .o suffix to the first line, and make will include them in the compilation. Also note how make will only compile changed files... Then you will need to add .h file dependencies when you get more .h files.

Static Initialization Fiasco - On Purpose

Just for fun, I was investigating the order of dynamic initialization of static objects.
In a file name t.h, I put
struct T {
static std::vector<std::string> me;
static int add(std::string s) { me.push_back(s); return me.size(); }
};
(Plus needed headers for vector and string.)
"std::vector T::me" is in t.cpp.
The file main.cpp prints out the values in T::me:
#include "t.h"
#include <iostream>
using namespace std;
int main()
{
T::me.push_back("main");
cout << "T::me.size()=" << T::me.size() << endl;
for (unsigned i = 0; i<T::me.size(); ++i) {
cout << i << "-" << T::me[i] << endl;
}
return 0;
}
next, I create "a.cpp" and put the following in it:
#include "t.h"
int a = T::add("a");
Do the similar for file b.cpp and c.cpp using "b" and "c" as appropriate.
Compile using g++ *.cpp, then run ./a.out. The order of static initialization from compilation unit to compilation unit is unspecified. In my case it is consistently in reverse alphabetical order. I get:
3 - c
2 - b
1 - a
0 - main
No problems so far.
Now I create u.cpp like a.cpp but using "u". Recompile/rerun, "u" does not show up in the list.
Is it because I never referenced u? I never referenced a,b,c, but I change main:
#include "t.h"
#include <iostream>
using namespace std;
extern int u;
int main()
{
cout << "u=" << u << endl;
T::me.push_back("main");
cout << "T::me.size()=" << T::me.size() << endl;
for (unsigned i = 0; i<T::me.size(); ++i) {
cout << i << "-" << T::me[i] << endl;
}
return 0;
}
The program prints out "u=2", but "u" is not in the list. Shouldn't u have been dynamically initialized before use and, therefore, T::me have been updated to include "u"? I think there should be a better explanation than that u comes after t in the alphabet.
I've got it. Simple, really.
T::me is zero initialized statically according to the rules of C++. There is a constructor, however, to run dynamically. There's no guarantee when that constructor runs. It is apparently - in this case - running after u is initialized.
It seems that the compilation linking order matters:
g++ -o m a.cpp u.cpp t.cpp main.cpp
gives
a=2
u=1
T::me.size()=3
0-u
1-a
2-main
but
g++ -o m main.cpp t.cpp a.cpp u.cpp
gives
a=2
u=1
T::me.size()=1
0-main
and reversing a.cpp and u.cpp in the last case causes a=1 and u=2.
Interesting!