需要帮助找到未定义的符号

时间:2014-10-22 14:25:48

标签: c++ gcc undefined-reference

我有一个程序正在编译而没有警告或错误,但是遇到了Undefined Reference问题。该程序包含三个文件。 mybash.cc是我写的文件。两个解析器文件是教授给出的开头代码。该程序将工作目录显示为shell提示符并接受命令。该命令通过解析进行分析,然后由mybash打印有关它的信息。我的所有Undefined Reference错误都不是函数,而是一堆乱七八糟的字符。我正在编译使用“gcc -g -Wall -Werror -O2 -c parser.c”,“gcc -g -Wall -Werror -O2 parser.o mybash.cc -o mybash”。我认为问题是链接器错误或我没有正确初始化/声明一些东西。但是,我很难找到问题。

编辑:这是未定义的错误,

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 个答案:

答案 0 :(得分:1)

正如molbdnilo所说,使用g ++来编译修复我的问题。但是,我的班级需要使用gcc。为了解决这个问题,我将parser.c更改为parser.cc并将-lstdc ++添加到我的编译器标志中。这允许我在两者上使用gcc并且仍然可以编译并运行而没有错误。