Having some linker problems with gcc...

Hello! I'm having some trouble getting my program to compile.

The purpose of this program is:

1.) To generate hour/temperature values and store them in a struct.
2.) To write the values of these hour/temperature pairs to a file.
3.) Read the hour/temperature pairs from the same file.
4.) Calculate and display the mean value of the temperature values.

The code compiles fine when everything is one file. I'm running into trouble when I split the code up into several files. Using gcc, I get a compiler error message: "duplicate symbols for architecture_x86_64". According to what I've read on Stack Overflow, this means that something is being double-included that shouldn't be.

I'd like to understand how to resolve this linker issue and avoid future linker issues.

Please keep in mind that this code is hacky and for learning about fstream objects. I have "using namespace std" for convenience's sake; it gets tiring to write std:: over and over. The point of this program is to learn about file input/output and fstream objects. I'd like to learn more about the linker/compiler process as it pertains to headers/includes/source files.

I'd appreciate any comments/suggestions/feedback that would make the program faster or the code more debuggable/elegant.

Here is the code!

////////////////////////////////////////////////////////////////temps.h
#ifndef _TEMPS_H
#define _TEMPS_H
#include <iostream>
#include <algorithm>
#include <vector>
#include <fstream>
#include <ctime>
#include <random>
#include <string>
#include "temps.h"

using namespace std;

void error (string s){
throw runtime_error(s);
}
void temp_stats(string fileName);

struct Reading{
int hour;
double temperature;
};

#endif


////////////////////////////////////////////////////////////////store_temps.cpp
void store_temps(string fileName){

ofstream ost{fileName};
if (!ost)
error("can't open output file");

vector<Reading> temps;
int hour = 0;
double temperature = 0;

//set Random seed
srand(time(NULL));

//Populate vector with temperature readings
for (int i = 0; i < 50; ++i){
hour = i;
temperature = (rand() % 100 + 1); //rand generator for doubles
temps.push_back(Reading{hour, temperature});
}

//Read into file raw_temps.txt
for (int i = 0; i < temps.size(); ++i)
ost << '(' << temps[i].hour << ", " << temps[i].temperature << ")\n";

return;
}


////////////////////////////////////////////////////////////////read_temps.cpp
#include "temps.h"

void read_temps(string fileName){

ifstream ist{fileName};
if (!ist)
error("can't open input file");

vector<Reading> temps;
vector<double> temps2;
int hour;
double temperature;
char ch1, ch2, ch3;
double mean;

while (ist >> ch1 >> hour >> ch2 >> temperature >> ch3){
temps.push_back(Reading{hour,temperature});
}

int sum = 0; //calculate mean temperature
for (int i = 0; i < temps.size(); ++i){
sum += temps[i].temperature;
temps2[i] = temps[i].temperature;
}
mean = sum / temps.size();

cout << "Mean temp: " << mean << endl;

}


/////////////////////////////////////////////////////////////////main.cpp
#include "temps.h"

using namespace std;

int main(){

string fileName{};
cout << "Enter filename: ";
getline(cin, fileName);

//
store_temps(fileName);


return 0;
}

ODR (One Definition Rule): Thou shalt not define same thing more than once.

1
2
3
4
void error (string s)
{
  throw runtime_error(s);
}

The implementation of void error(std::string) exists in multiple translation units. Move it to exactly one of the source files.
Ok cool, but if I move the function to one of the source files and use it in another one won't I have to include a .cpp file? And isn't that bad practice? Thanks for the help!
OHHHHHH. I figured it out. The problem was that I defined void error(string s) in my .h file instead of declaring a function prototype. As you correctly stated, the function definition needs to be in just one .cpp file to avoid double-include issues. Thank you!

So, solution:

1.) Make void error(string s) a function prototype in the .h file.
2.) Place the implementation in just one .cpp file
Last edited on
also when you compile be sure to list all the .cpp names:
g++ -std=c++11 main.cpp store_temps.cpp read_temps.cpp
so your files can get linked properly
Last edited on
Topic archived. No new replies allowed.