C++ 未定义的引用和分段错误

C++ 未定义的引用和分段错误,c++,g++,segmentation-fault,undefined-reference,C++,G++,Segmentation Fault,Undefined Reference,好的,我正在编写一个程序,它使用几个不同的类,包括一个链接排序列表和一个二叉搜索树/节点类。当我在VisualStudio中编译时,它运行时没有任何抱怨,100%平滑,我已经在那里完全调试了它,没有错误。然而,当我把它放到Unix中时,我必须打开它,然后用g++测试它,一切都糟透了。如果我试图访问比二叉树的根更多的内容,就会出现“分段错误” 当我使用命令“g++main.cpp”时,我看到许多对其他类的成员函数的“未定义引用”。现在,我有了所有必要的#include语句,以及使用“#ifndef

好的,我正在编写一个程序,它使用几个不同的类,包括一个链接排序列表和一个二叉搜索树/节点类。当我在VisualStudio中编译时,它运行时没有任何抱怨,100%平滑,我已经在那里完全调试了它,没有错误。然而,当我把它放到Unix中时,我必须打开它,然后用g++测试它,一切都糟透了。如果我试图访问比二叉树的根更多的内容,就会出现“分段错误”

当我使用命令“g++main.cpp”时,我看到许多对其他类的成员函数的“未定义引用”。现在,我有了所有必要的#include语句,以及使用“#ifndef/#define/#endif”语句。只有Employee和SearchTreeNode两个类给出了这些问题。以下是这两个方面以及主要方面:

    #include "LinkedSortedList.h"
    #include "LinkedNode.h"
    #include "Employee.h"
    #include "SearchTreeNode.h"
    #include <string>
    #include <ostream>
    #include <iostream>
    #include <fstream>

    using namespace std;

    int main() {

LinkedSortedList<Employee> mylist;  //create the LSL
SearchTree mytree;                  //create the BST

int searchCount = 0; //occasionally used to count recursive calls to function
bool _continue = true;
char command;

do{

    cout << "\nEnter your command: \n" << endl;
    cout << "(I)nsert\n(F)ind Employee from ID\n(D)elete Employee from ID\n(L)ast Name Search\n(S)ave to file\n(R)ead from file\n(Q)uit" << endl;

    cin >> command;

    if(command == 'I' || command == 'i'){
        //insert
        Employee* newEmployee = new Employee();
        newEmployee->create();
        mylist.insert(*newEmployee);
        mytree.insert(newEmployee);
        cout << "Employee Added\n----------\n" << endl;
        newEmployee->print();
        cout << "\n----------\n" << endl;
    }
    else if(command == 'L' || command == 'l'){
        //arbitrary pointer to undefined matches to be used in fetchAllMatches()
        LinkedSortedList<Employee>* matches;
        string name;
        cout << "Last Name to Search for: " << endl;
        cin >> name;
        Employee* search = new Employee();
        search->setLastName(name);

        int matchCount = mylist.fetchAllMatches(*search, matches, matchCount);
        cout << mylist.size() << " Records Searched.\n"<< matchCount << " Matches Found:" << endl;
        //Make sure that there is something to print to avoid errors
        if(matchCount > 0)
            matches->print();

    }
    else if(command == 'D' || command == 'd'){
        int IDnumber;
        cout << "Enter Employee ID to delete: " << endl;
        cin >> IDnumber;

        if(mytree.getRoot() != NULL) { // make sure there is a tree to search through
            Employee *x = mytree.find(IDnumber, searchCount, mytree.getRoot());

            if(x->getAddress() != "null"){
                mylist.remove(*x);
                mytree.remove(x->getId());
                cout << "\n" << x << "\n---------\n" << "File Deleted" << endl;
            }

        } else {
            cout << "Tree is empty" << endl;
        }
    }
    else if(command == 'F' || command == 'f'){
        int IDnumber;
        cout << "Enter Employee ID to find: " << endl;
        cin >> IDnumber;
        searchCount = 0;
        if(mytree.getRoot() != NULL) { // make sure there is a tree to search through
            Employee* x = mytree.find(IDnumber, searchCount, mytree.getRoot());

            if(x->getAddress() != "null"){
                    cout << "\n" << *x << "\n" << endl;
            } else {
                cout << "Employee not found!" << endl;
            }

        } else {
            cout << "Tree is empty" << endl;
        }
    }
    else if(command == 'S' || command == 's'){
        string file;
        cout << "Write Database to File Name: " << endl;
        cin >> file;
        mylist.printToFile(file, mylist);
    }
    else if(command == 'T' || command == 't'){
        mytree.print(mytree.getRoot());
    }
    else if(command == 'R' || command == 'r'){
        //read
        if(mylist.size() > 0) {
            mylist.clear();
            mytree.clearTree(mytree);
        }
        string line;
        string file;
        int intLine;
        cout << "File Name: " << endl;
        cin >> file;
        ifstream myfile(file.c_str());
        if (myfile.is_open())
        {
            getline (myfile,line);
            if(line != "<Records>"){
                cout << "Not a database file." << endl;
            }
            //make sure it's still ok
            while ( myfile.good() )
            {

                getline(myfile, line);
                if(line != "<END>"){

                    Employee* newEmployee = new Employee();

                    for(int i = 0; i < 10; i++){
                        switch (i){

                        case 0:

                            newEmployee->setLastName(line);
                            break;
                        case 1:
                            getline(myfile, line);
                            newEmployee->setFirstName(line);
                            break;
                        case 2:
                            myfile >> intLine;
                            newEmployee->setId(intLine);
                            break;
                        case 3:
                            myfile >> intLine;
                            myfile.get();
                            newEmployee->setSalary(intLine);
                            break;
                        case 4:
                            getline(myfile, line);
                            newEmployee->setDept(line);
                            break;
                        case 5:
                            getline(myfile, line);
                            newEmployee->setPhone(line);
                            break;
                        case 6:
                            getline(myfile, line);
                            newEmployee->setAddress(line);
                            break;
                        case 7:
                            getline(myfile, line);
                            newEmployee->setHireDate(line);
                            break;
                        case 8:
                            getline(myfile, line);
                            newEmployee->setEmail(line);
                            break;
                        case 9:
                            getline(myfile, line);//eat the dashes
                            break;
                        }

                    }
                    mylist.insert(*newEmployee);
                    mytree.insert(newEmployee);
                }
                else {
                    myfile.close();
                }
            }

        }
        else cout << "Unable to open file";     
    }
    else if(command == 'Q' || command == 'q'){
        return 0;
    }
    else if(command == 'P' || command == 'p'){
        mylist.print();
    }
}
while(_continue);

return 0;
}






    #include <iostream>
    using namespace std;



    #ifndef _EmployeeClass_
    #define _EmployeeClass_


    class Employee {

    public:

Employee(){
    firstName;
    lastName;
    department;
    email;
    dateHired;
    phoneNumber;
    homeAddress;
    employeeID = 0;
    salary = 0;

    //this->create();
}

Employee(string last, string first, int ID, int _salary, string dept, string phone, 
    string address, string hireDate, string _email){

        lastName = last;
        firstName = first;
        employeeID = ID;
        salary = _salary;
        department = dept;
        phoneNumber = phone;
        homeAddress = address;
        dateHired = hireDate;
        email = _email;

        employeeCount++;
}

void create();
//list of getter functions to return private variables, preventing direct access.
int getId();
int getSalary();
string getFirstName();
string getLastName();
string getDept();
string getHireDate();
string getEmail();
string getAddress();
string getPhone();

friend bool operator!= (Employee &x, Employee &y);
friend bool operator== (Employee &x, Employee &y);  
friend bool operator<= (Employee &x, Employee &y);
friend bool operator>= (Employee &x, Employee &y);
friend bool operator< (Employee &x, Employee &y);
friend bool operator> (Employee &x, Employee &y);

friend ostream& operator<<(ostream& output, Employee& x);
void print();

//list of setter functions to set values for the private variables, without allowing direct access.
void setPhone(string phone);
void setId(int ID);
void setSalary(int salary);
void setFirstName(string name);
void setLastName(string surname);
void setDept(string dept);
void setHireDate(string hireDate);
void setEmail(string email);
void setAddress(string address);

    private:

//private member variables dependant on input for each individual object
string firstName;
string lastName;
string department;
string email;
string dateHired;
string homeAddress;
string phoneNumber;
int employeeID;
int salary;

int employeeCount;

    };

    #endif
#包括“LinkedSortedList.h”
#包括“LinkedNode.h”
#包括“Employee.h”
#包括“SearchTreeNode.h”
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
LinkedSortedList mylist;//创建LSL
SearchTree mytree;//创建BST
int searchCount=0;//偶尔用于计算对函数的递归调用
bool _continue=true;
char命令;
做{

cout出现这些问题的原因可能有很多。我想到的一个原因是,当您在Visual Studio中编译时,您已经设置了包含路径——搜索头文件的路径。也可能您没有在Visual Studio中设置它,但在创建项目并添加从不同目录将文件添加到项目中

使用g++,您必须自己提供include目录。(如果您在Linux下使用了类似于Visual Studio的IDE,那么这些包含目录将为您设置。因此,问题不在于Windows和Linux之间的区别,而在于在IDE中进行幕后开发和使用命令行编译之间的区别。)

查看g++的手册页。查看用于添加包含目录的-I选项和用于链接期间库搜索的-l选项。(很可能您需要-I选项。)

鉴于您成功地使用了Windows,我怀疑您的源代码是否有问题。唯一的另一种可能是您使用了Visual Studio特有的库函数,这在g++中是不存在的。

每当您尝试读取或写入无效内存地址时,就会出现分段错误。这可能有许多原因-c请看一些例子

如果无法链接所需的库和/或对象文件,则会发生未定义的引用错误。从简单使用
g++main.cpp
开始,您既没有指定其他源文件,也没有指定链接所需的任何库

正如上面所说的@Ray,当直接在命令行上编译时,您必须自己提供include和linking目录,这就是为什么我们通常有一个Makefile。使用一个精心编制的Makefile比直接调用编译器要好,因为它会检查哪些源文件发生了更改,调用编译器只重新生成源文件需要的是文件,而不是所有的东西(当你的项目很大的时候,这会有很大的不同!)

如果您对Makefiles没有太多经验,我建议您使用。它是一个为您生成Makefiles的构建系统。好的是它甚至是多平台的,因此使用相同的CMakeLists.txt文件,您可以为Windows或Linux生成Makefiles,语法非常简单

如果您告诉我您拥有的所有源文件以及您可能使用的最终库,我可以为您提供一个确切的CMakeLists.txt示例,该示例将为您编译所有内容,但它可以是如下所示的简单示例(根据您的include,我假设您的源文件是main.cpp、LinkedSortedList.cpp、LinkedNode.cpp、Employee.cpp和SearchTreeNode.cpp):

您应该在源代码目录下创建此文件。要将编译输出与源代码分开,然后可以创建一个构建目录,请在父目录下引用CMakeLists.txt文件运行CMake,它将为您构建Makefile。从那里,您只需调用常规make来构建程序:

mkdir build
cd build
cmake ..
make

这会将可执行文件employee\u manager放入build目录中。

答案会非常有用:/好吧,你没有花太多时间来处理。也许阅读会有所帮助。真的……我想问题的确切代码段,以及问题的非常具体的示例都不太清楚不,我的错。如果你真的相信这是事实,那么为什么你没有收到任何有用的回复呢?我已经搜索了一个多小时。如果我在其他地方看到了这个问题的准确描述,我就不会发帖了。我唯一有问题的帖子要么是a)没有“有用的回复”,B)一个非常简单的版本。我使用的唯一库函数是iostream、fstream、ostream和string。所有文件都在同一个目录中;我使用的是makefile,但所有依赖项似乎都是正确的。我仅有的include语句用于访问其成员的必要类Actions/variables.抱歉,我指的是你的文件的头文件。它们都在同一个目录中吗?如果它们甚至在子目录中,那么你需要-I选项。另一方面,如果你的所有头文件都在同一个目录中,那么你应该检查iostream等是否被正确定位。错误是否与丢失有关你的函数或库函数的函数?也许你可以用这些错误消息更新你的帖子(如果有很多,前10个左右就可以了)。至于makefile,它们通常是手工制作的。它们很棘手
cmake_minimum_required (VERSION 2.6)

project (employee_manager CXX)

set (SOURCES
  main.cpp
  LinkedSortedList.cpp
  LinkedNode.cpp
  Employee.cpp
  SearchTreeNode.cpp
  )

add_executable (employee_manager ${SOURCES})
mkdir build
cd build
cmake ..
make