问题
I have a program that is compiling without warnings or errors but is hitting Undefined Reference problems. The program consists of three files. mybash.cc is a file I wrote. The two parser files were head start code given by a professor. The program is to display the working directory as a shell prompt and take in a command. The command is analyzed by parse and then information about it is printed by mybash. All of my Undefined Reference errors are not functions but a mess of characters. I am compiling using "gcc -g -Wall -Werror -O2 -c parser.c", "gcc -g -Wall -Werror -O2 parser.o mybash.cc -o mybash". I assume the problem is a linker error or I am not initializing/declaring something correctly. However, I am having trouble finding the problem.
Edit: Here are the undefined errors,
p1% make
gcc -g -Wall -Werror -O2 -c parser.c
gcc -g -Wall -Werror -O2 parser.o mybash.cc -o mybash
Undefined first referenced
symbol in file
_ZNKSt5ctypeIcE13_M_widen_initEv /var/tmp//ccQT23cT.o
_Z16ParseCommandLinePcP11CommandData /var/tmp//ccQT23cT.o
_ZNSo3putEc /var/tmp//ccQT23cT.o
_ZNSolsEi /var/tmp//ccQT23cT.o
_ZSt16__throw_bad_castv /var/tmp//ccQT23cT.o
_ZNSs4_Rep20_S_empty_rep_storageE /var/tmp//ccQT23cT.o
_ZNKSs7compareEPKc /var/tmp//ccQT23cT.o
_ZNSo5flushEv /var/tmp//ccQT23cT.o
_ZSt4cout /var/tmp//ccQT23cT.o
_ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate /var/tmp//ccQT23cT.o
_ZNSs4_Rep10_M_destroyERKSaIcE /var/tmp//ccQT23cT.o
_ZNSt8ios_base4InitD1Ev /var/tmp//ccQT23cT.o
_ZNSt8ios_base4InitC1Ev /var/tmp//ccQT23cT.o
__gxx_personality_v0 /var/tmp//ccQT23cT.o
_ZNSs6assignEPKcj /var/tmp//ccQT23cT.o
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc /var/tmp//ccQT23cT.o
_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_i /var/tmp//ccQT23cT.o
_ZNSi7getlineEPcic /var/tmp//ccQT23cT.o
_ZSt3cin /var/tmp//ccQT23cT.o
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ /var/tmp//ccQT23cT.o
ld: fatal: symbol referencing errors. No output written to mybash
*** Error code 1
make: Fatal error: Command failed for target `mybash'
p1%
mybash.cc
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include "parser.h"
using namespace std;
// an integer used for maximum values of command line arguments
static const int MAX = 128;
int main(int argc, char *argv[])
{
//do this infinitely or until exit is entered
while (true) {
// display the current working directory and catch the value in holder because getcwd() doesnt work
char holder[MAX];
cout << getcwd(holder, MAX) << "> ";
// get the commands from the user
char commands[MAX];
cin.getline(commands, 128);
// create a CommandData object for use in ParseCommandLine
struct CommandData parsedCommands;
int catcher;
// catch the return and fill data from ParseCommandLine by input from commands
catcher = ParseCommandLine(commands, &parsedCommands);
// if ParseCommandLine returns an error, stop and ask for new input
if (catcher == 0) { cout << "Parsing Error, re-enter command" << endl << endl; }
// if ParseCommandLine finishes correctly
else {
// string used to compare and display char[] easily
string printIt;
// display statements to describe the command input
cout << endl << "Number of simple commands : " << parsedCommands.numcommands << endl;
// if there are multiple commands, display all of them
for (int i = 0; i < parsedCommands.numcommands; i++) {
printIt = parsedCommands.TheCommands[i].command;
cout << "command " << (i+1) << " : " << printIt << endl;
// if there are args display all of them
for (int j = 0; j < parsedCommands.TheCommands[i].numargs; j++) {
printIt = parsedCommands.TheCommands[i].args[j];
cout << "arg[" << j << "] : " << printIt << endl;
}
}
// display the infile if there is one, otherwise NULL
printIt = parsedCommands.infile;
if (parsedCommands.infile) { cout << "Input file : " << printIt << endl; }
else { cout << "Input file : NULL" << endl; }
// display the outfile if there is one, otherwise NULL
printIt = parsedCommands.outfile;
if (parsedCommands.outfile) { cout << "Output file : " << printIt << endl; }
else { cout << "Output file : NULL" << endl; }
// display whether or not the command is to run in the foreground or background
if (parsedCommands.background == 0) { cout << "Background option : OFF" << endl; }
else { cout << "Background option : ON" << endl; }
// the only current built in command is exit, so if exit, display yes and exit, otherwise display no
printIt = parsedCommands.TheCommands[0].command;
if (printIt == "exit") {
cout << "Built-in command : YES" << endl << endl;
return 0;
}
else { cout << "Built-in command : NO" << endl; }
}
}
exit(0);
}
parser.h
#define COMMAND 1
#define ARG 2
#define INFILE 3
#define OUTFILE 4
#define UNDEF 5
struct Command {
char *command;
char *args[11];
int numargs;
};
struct CommandData {
struct Command TheCommands[20]; /* the commands to be
executed. TheCommands[0] is the first command
to be executed. Its output is piped to
TheCommands[1], etc. */
int numcommands; /* the number of commands in the above array */
char *infile; /* the file for input redirection, NULL if none */
char *outfile; /* the file for output redirection, NULL if none */
int background; /* 0 if process is to run in foreground, 1 if in background */
};
extern int ParseCommandLine(char *, struct CommandData *);
parser.cc
int ParseCommandLine(char *line, struct CommandData *data)
{
int i, j;
char token[256];
int inaword;
int state;
i=0;
j=0;
inaword = 0;
state = COMMAND;
data->numcommands = 0;
data->TheCommands[0].command=NULL;
data->infile = data->outfile = NULL;
data->background = 0;
while (line[i] != '\0' && line[i] != '\n') {
if (IsAlphaNum(line[i])) {
if (inaword) {
token[j++]=line[i];
}
else { /* starting a new word */
j = 0;
token[j++] = line[i];
inaword = 1;
}
}
else { /* not an alphanumeric character */
if (inaword) { /* we have found the end of a token */
token[j]='\0';
inaword = 0;
if (CopyWord(token,data,&state)==0)
return 0;
}
switch (line[i]) {
case ' ':
break;
case '>':
if (state == OUTFILE || state == INFILE || state == COMMAND) {
fprintf(stderr, "Error, bad syntax on the command line\n");
return 0;
}
state = OUTFILE;
break;
case '<':
if (state == OUTFILE || state == INFILE || state == COMMAND) {
fprintf(stderr, "Error, bad syntax on the command line\n");
return 0;
}
state = INFILE;
break;
case '|':
if (state == COMMAND || state == INFILE || state == OUTFILE) {
fprintf(stderr, "Error, bad syntax on the command line\n");
return 0;
}
data->numcommands++;
state = COMMAND;
data->TheCommands[data->numcommands].command = NULL;
data->TheCommands[data->numcommands].numargs = 0;
break;
case '&':
if (state == OUTFILE || state == INFILE || state == COMMAND) {
fprintf(stderr, "Error, bad syntax on the command line\n");
return 0;
}
data->background = 1;
break;
default :
fprintf(stderr,"Error, invalid character on command line %c\n",line[i]);
return 0;
}; /* end of switch */
} /* end of else */
i++;
} /* end of while loop */
/* we have gotten to the end of the line, there may still be a
string that has not been processed */
if (inaword) {
token[j]='\0';
if (CopyWord(token,data,&state)==0) {
return 0;
}
}
/* do some final error checking */
if (state == INFILE && data->infile == NULL) {
fprintf(stderr,"Error, < but no filename\n");
return 0;
}
if (state == OUTFILE && data->outfile == NULL) {
fprintf(stderr,"Error, > but no filename\n");
return 0;
}
if (state == COMMAND) {
fprintf(stderr,"Error, bad syntax on command line\n");
return 0;
}
if (data->TheCommands[0].command == NULL) {
fprintf(stderr, "Error, no command\n");
return 0;
}
data->numcommands++;
return 1;
}
回答1:
As molbdnilo stated, using g++ to compile both fixed my issues. However, my class required use of gcc. To fix this, I changed parser.c to parser.cc and added -lstdc++ to my compiler flags. This allowed me to use gcc on both and still have it compile and run without errors.
来源:https://stackoverflow.com/questions/26509847/need-help-finding-undefined-symbols