eclipse - ld : Symbol(s) not found… but they are there…

标签 eclipse macos linker g++

我的项目最近真的很糟糕——我解决了一大堆错误,然后它抛出了一个神秘的 ld: symbol(s) not found 错误。但是,很明显这些符号确实存在:

Undefined symbols:
  "Solid::~Solid()", referenced from:
      void std::_Destroy<Solid>(Solid*)in ui.o
  "Log::operator+=(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
      runUI()    in ui.o
  "Log::getLog(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
      runUI()    in ui.o
  "Log::Log()", referenced from:
      __static_initialization_and_destruction_0(int, int)in ui.o
  "Building::Building(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
      runUI()    in ui.o
  "Log::~Log()", referenced from:
      ___tcf_1 in ui.o

这是它引用的文件:

日志.cpp

/*
 * log.cpp
 *
 *  Created on: Apr 30, 2011
 *      Author: wjc
 */

#include <string>
#include <vector>
#include <sstream> // for converting count to string
#include "consts.h"
using namespace std;

struct logResult {
    vector <string> result;
    int status;
};

struct parsedLog {
    string result;
    int status;
};

class Log {

private:
    bool initialized;
    vector <string> * actionLog;
    static int count;
    string countString(){
        stringstream ss;
        ss<<count;
        return ss.str();
    }
public:
    int initialize(){
        if (initialized) return ALREADY_INIT;
        actionLog->push_back("*** Log initialized ***");
        actionLog->push_back("This is log#" + countString() +". If this is greater than one, there is a problem.");
        initialized = true;
        return SUCCESS;
    }
    int initialize(string text){
        int initResult = initialize();
        if (initResult == ALREADY_INIT) return ALREADY_INIT;
        actionLog->push_back("Initialization message: "+text);
        return SUCCESS;
    }
    Log (){
        initialize();
        count++;
    }
    Log (string text){
        initialize(text);
        count++;
    }
    ~Log (){
        count--;
    }
    bool isInitialized(){
        return initialized;
    }
    int add(string text){
        if (!initialized) return NOT_INIT;
        actionLog->push_back(text);
        return SUCCESS;
    }
    int operator+= (string text){
        return add(text);
    }
    int clearLog(bool init = true){
        if (!initialized) return NOT_INIT;
        delete actionLog;
        int initResult = SUCCESS;
        if (init) initResult = initialize();
        if (initResult == ALREADY_INIT) return ALREADY_INIT;
        // Otherwise
        // (no other possibilities because initialize()
        //  only returns either a SUCCESS or
        //  ALREADY_INIT value)
        return SUCCESS;
    }
    logResult getLog(){
        if (!initialized){
            logResult final;
            final.status = NOT_INIT;
            return final;
        } else {
            logResult final;
            final.result = *actionLog;
            final.status = SUCCESS;
            return final;
        }
    }
    parsedLog getLog(string delim){
        if (!initialized){
            parsedLog final;
            final.status = NOT_INIT;
            return final;
        } else {
            parsedLog final;
            string logString;
            for (unsigned int i; i<actionLog->size()-1; i++){
                logString += (*actionLog)[i];
                logString += delim;
            }
            logString += actionLog->back();
            final.result = logString;
            final.status = SUCCESS;
            return final;
        }
    }
};

日志.h

/*
 * log.h
 *
 *  Created on: Apr 30, 2011
 *      Author: wjc
 */

#ifndef LOG_H_
#define LOG_H_
#include <string>
using namespace std;

struct logResult {
    vector <string> result;
    int status;
};

struct parsedLog {
    string result;
    int status;
};

class Log {
public:
    int initialize();
    int initialize(string text);
    Log ();
    Log (string text);
    ~Log();
    bool isInitialized;
    int add(string text);
    int operator+= (string text);
    int clearLog (bool init = true);
    vector <string> getLog();
    parsedLog getLog(string delim);
private:
    bool initialized;
    vector <string> actionLog;
    static int count;
    string countString();
};

#endif /* LOG_H_ */

用户界面.cppp

/*
 *  Created on: Apr 26, 2011
 * ui.cpp
 *      Author: wjc
 */

#include <iostream>
#include <vector>
#include <sstream>

#include "filedaemon.h"
#include "vsystem.h"
#include "customio.h"
#include "building.h"
#include "log.h"

using namespace std;

bool shouldexit = false;
bool back = false;
int selection;

void addShape();
void modifyVars();
struct getVarResult {
    var result;
    int status;
};

Log actionLog;

var novar = {"ERROR", -1, Reserved};

getVarResult getVar(int type);
void viewBuilding();

int runUI(){
    while (!shouldexit){
        cout<<"Please select an item from the list below and press Enter:"<<endl;

        const int mmenuLength = 2;
        string mmenuOptions[2] = {"Create a new document","Quit"};
        for (int i=0; i<2; i++){
            cout<<i+1<<": "<<mmenuOptions[i]<<endl;
        } cout<<endl;
        selection = getMenuItem(1,mmenuLength);

        if (selection == mmenuLength) return 0; // Quit if it's the last one

        cout<<"Enter a name for your building:"<<endl;
        string buildingTitle;
        getline(cin, buildingTitle);

        Building b(buildingTitle);
        actionLog += "New building " + buildingTitle + " created.";

        const int bmenuLength = 5;
        string bmenuOptions[5] = {"Add shape","Modify variables","View building","View log","Quit"};
        for (int i=0; i<bmenuLength; i++){
            cout<<i+1<<": "<<bmenuOptions[i]<<endl;
        } cout<<endl;
        selection = getMenuItem(1,bmenuLength);

        switch (selection){
        case 1:
            // Add a shape
            break;
        case 2:
            modifyVars();
            break;
        case 3:
            // View building
            break;
        case 4:
        {
            parsedLog parsed = actionLog.getLog("\n");
            if (parsed.status == SUCCESS) {
                cout<<"The following contains the contents of your action log."<<endl;
                cout<<parsed.result<<endl<<endl;
            } else {
                cout<<"Somehow your log is not initialized."<<endl<<endl;
            }
        }
            break;
        case 5:
            shouldexit = true;
            break;
        default:
            cout<<"You entered a number greater than "<<bmenuLength<<" or less than 1. How you did this is a mystery."<<endl<<"[ Press Enter to exit ]"<<endl;
            string temp;
            getline(cin, temp);
            return 0;
        }
        // The following commented-out block is a
        // test of the variable storing system.
        // It will not be used in any final products.

        /*cout << "   Variable Systems Test   "<<endl;
    cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
    cout << endl;
    cout<<"Enter a variable name:"<<endl;
    string varname;
    cin>>varname;
    cout<<"Enter a value (A FLOAT!):"<<endl;
    float value;
    cin>>value;
    cout<<"Checking to see if "<<varname<<" exists."<<endl;
    bool alreadythere = checkVar(varname);
    alreadythere ? cout<<"It exists!"<<endl : cout<<"It doesn't exist."<<endl;
    if (alreadythere){
        cout<<"Changing variable. Function returned "<<changeVar(varname, value)<<endl;
    } else {
        cout<<"Setting variable. Function returned "<<addVar(varname, value)<<endl;
    }
    cout<<"Enter a variable to check:"<<endl;
    string varcheck;
    cin>>varcheck;
    fetchResult result = fetchVar(varcheck);
    if(! result.good){
        cout<<"Variable \""<<varcheck<<"\" doesn't exist!"<<endl;
    } else {
        cout<<"Variable \""<<varcheck<<"\" is equal to "<<result.result<<endl;
    }
    cout<<getVarList("\n","\t")<<endl;
    string exitstr;
    getch;*/
    }
    return 0;
}

void modifyVars(){
    while (! back){
        cout<<"These are your defined variables."<<endl;
        cout<<"Reserved variables have an asterisk preceding them."<<endl;
        vector <var> vars = getVarList();
        for (unsigned int i = 0; i<vars.size(); i++){
            cout<<endl;
            vars[i].reserved ? cout<<" * " : cout<<"   ";
            cout << vars[i].name<<" = ";
            cout<<fixed<<vars[i].value;
        }cout<<endl;
        cout<<"What would you like to do?"<<endl;
        string varMenuOptions[4] = {"Add a variable","Change a variable","Remove a variable","Go back"};
        for (int i = 0; i<4; i++){
            cout<<i+1<<". "<<varMenuOptions[i]<<endl;
        } cout<<endl;
        selection = getMenuItem(1,3);
        switch(selection){
        case 1: // Add variable
        {
            getVarResult gvr = getVar(ADD);
            if (gvr.status == SUCCESS)
                addVar(gvr.result.name, gvr.result.value, UserDefined);
            break;
        }
        case 2: // Change variable
        {
            getVarResult gvr = getVar(CHANGE);
            if (gvr.status == SUCCESS)
                changeVar(gvr.result.name, gvr.result.value);
            break;
        } // switch (selection)
        } // while (!back)
    }
}
getVarResult getVar(int type){
    getVarResult finalResult;
    getVarResult invalidType;
    getVarResult cancelled;
    invalidType.result = novar;
    invalidType.status = INVALID_TYPE;
    cancelled.result = novar;
    cancelled.status = USER_CANCELLED;
    if (type != ADD && type != CHANGE) return invalidType;
    bool usercancelled = false;
    bool nameOK = true;
    bool varIsReserved = false;
    string varName;
    do {
        switch(type){
        case ADD:
            if (!nameOK) cout<<"That variable already exists."<<endl;
            break;
        case CHANGE:
            if (!nameOK) cout<<"That variable has not yet been created."<<endl;
            if (varIsReserved) cout<<"That variable is used by the system and cannot be changed."<<endl;
            break;
        }
        cout<<"Enter the variable's name, or \"BACK\": "; varName = getString(1,16);
        if (varName == "BACK"){
            usercancelled = true;
            break;
        }
        fetchResult testExist = fetchVar(varName);
        switch(type){
        case ADD:
            nameOK = !testExist.good;
            break;
        case CHANGE:
            nameOK = testExist.good;
            varIsReserved = testExist.reserved;
            break;
        default:
            cout << "Function error - int type seems to have changed since user called getVar(int type)."<<endl;
            cout << "[ Press Enter to exit]"<<endl;
            string temp;
            getline(cin, temp);
            return invalidType;
        }
    } while (! nameOK || varIsReserved);
    finalResult.result.name = varName;
    if (usercancelled) return cancelled;
    bool valueOK = true;
    float numValue;
    do {
        if (! valueOK) cout<<"That doesn't seem to be a valid positive number.";
        cout<<"Enter the new value, or \"COPY\" to copy a variable, or \"BACK\":"<<endl;
        string value = getString();

        /*
         * If "BACK" then break do-while(! valueOK)
         */

        if (value == "BACK"){
            usercancelled = true;
            break;
        }
        if(value == "COPY"){
            string copyVar;
            fetchResult varContents;
            bool copyOK = true;
            do {
                if (!copyOK) cout<<"That variable does not exist. Note that names are case-sensitive."<<endl;
                cout<<"Enter the variable to copy, \"VIEW\" to view all, or \"BACK\":"<<endl;
                /*
                 * If "BACK" then break do-while(! valueOK)
                 */
                if (value == "BACK"){
                    usercancelled = true;
                    break;
                }
                copyVar = getString(1,8);
                if (copyVar == "VIEW") {
                    cout<<"Your current variables are as follows:"<<endl;
                    vector <var> vars = getVarList();
                    for (unsigned int i = 0; i<vars.size(); i++){
                        cout<<endl;
                        vars[i].reserved ? cout<<" * " : cout<<"   ";
                        cout << vars[i].name<<" = ";
                        cout<<fixed<<vars[i].value;
                    }cout<<endl;
                } else {
                    varContents = fetchVar(copyVar);
                    copyOK = varContents.good;
                    numValue = varContents.result;
                }
            } while (copyVar == "VIEW" || ! copyOK);
        } else {
            // This code converts from string to number safely.
            stringstream testStream(value);
            if (! (testStream >> numValue))
                valueOK = false;
        }
        if (! usercancelled) break;
    } while (! valueOK);
    finalResult.result.value = numValue;
    if (usercancelled) return cancelled;
    finalResult.status = SUCCESS;
    return finalResult;
}

ui.h

/*
 * ui.h
 *
 *  Created on: Apr 26, 2011
 *      Author: wjc
 */

#ifndef UI_H_
#define UI_H_

#include "vsystem.h"

int runUI();
void addShape();
void modifyVars();
struct getVarResult {
    var result;
    int status;
};
getVarResult getVar(int type);
void viewBuilding();

#endif /* UI_H_ */

建筑.h

/*
 * building.h
 *
 *  Created on: Apr 30, 2011
 *      Author: wjc
 */

#ifndef BUILDING_H_
#define BUILDING_H_

#include <string>
#include <vector>
#include "consts.h"
#include "solid_type.h"

using namespace std;

struct dimension {
    bool exists;
    float value;
};

class Solid {
public:
    string name;
    string comment;
    solid_type type;
    bool positive;
    dimension dim1;   // Radius, width, or side length
    dimension dim2;   // Height, number of sides, or fraction of sphere_over_n
    dimension dim3;   // Width - only for prism_rect, pyrm_rect and tprym_rect
    Solid ();
    Solid (bool pos);
    Solid (string setName, string setComment, solid_type setType, bool setPos, dimension setDim1,
            dimension setDim2, dimension setDim3);
    ~Solid();
    int countShapes();
    int howMany();
private:
    static int count;
};

class Building {
private:
    string name;
    vector <Solid> components;
public:
    Building(string text);
    void setName(string text);
    string getName();
    vector <Solid> addComponent(Solid component);
};

#endif /* BUILDING_H_ */

建筑.cpp

/*
 * building.cpp
 *
 *  Created on: May 1, 2011
 *      Author: wjc
 */

#include <string>
#include <vector>

#include "consts.h"
#include "solid_type.h"

using namespace std;

struct dimension {
    bool exists;
    float value;
};

class Solid{
public:
    string name;      // So the user can look at the log
    string comment;   // Expanded version of name, again for the log
    solid_type type;  // Determines the type of Solid
    bool positive;    // Positive = addition; negative = subtraction
    dimension dim1;   // Radius, width, or side length
    dimension dim2;   // Height, number of sides, or fraction of sphere_over_n
    dimension dim3;   // Width - only for prism_rect, pyrm_rect and tprym_rect
    Solid(){
        count++;
    }
    Solid(bool setPos){
        count++;
        positive = setPos;
    }
    Solid (string setName, string setComment, solid_type setType, bool setPos, dimension setDim1,
            dimension setDim2, dimension setDim3){
        count++;
        name = setName;
        comment = setComment;
        type = setType;
        positive = setPos;
        dim1 = setDim1;
        dim2 = setDim2;
        dim3 = setDim3;
    }
    ~Solid(){
        count--;
    }
    int howMany(){
        return count;
    }
    int countSolids(){
        return howMany();
    }
private:
    static int count; // Number of Solids in existence
};

class Building {
private:
    string name;
    vector <Solid> components;
public:
    Building (string text){
        setName(text);
    }
    void setName(string text) {
        name = text;
    }
    string getName(){
        return name;
    }
    vector <Solid> addComponent(Solid component){
        components.push_back(component);
        return components;
    }
};

我的完整代码可在 FileDropper 获得,虽然我知道大多数人不想解压一个 zip,所以我把相关的放在上面。 任何帮助将不胜感激!

在 Mac OS X Snow Leopard 10.6.7 上使用 G++ 4.2.1 运行 Eclipse Helios。


完整的链接命令是:

g++ -o "BuildingGenerator" ./src/bgmath.o ./src/building.o ./src/customio.o \
    ./src/filedaemon.o ./src/log.o ./src/main.o ./src/ui.o ./src/vsystem.o

所以看起来它正在链接所有必要的文件。此外,(头)文件在需要的地方都是#include

最佳答案

发现问题;大纲修复已创建...

代码接收、解压和编译;链接器产生的错误与您看到的基本相同...

Osiris-8 JL: make bgmath.o building.o customio.o filedaemon.o log.o main.o ui.o vsystem.o
g++    -c -o bgmath.o bgmath.cpp
g++    -c -o building.o building.cpp
g++    -c -o customio.o customio.cpp
g++    -c -o filedaemon.o filedaemon.cpp
g++    -c -o log.o log.cpp
g++    -c -o main.o main.cpp
g++    -c -o ui.o ui.cpp
g++    -c -o vsystem.o vsystem.cpp
Osiris-8 JL: g++ -o cmd *.o
Undefined symbols for architecture x86_64:
  "Building::Building(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
      runUI()    in ui.o
  "Log::operator+=(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
      runUI()    in ui.o
  "Log::getLog(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
      runUI()    in ui.o
  "Log::Log()", referenced from:
      __static_initialization_and_destruction_0(int, int) in ui.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Osiris-8 JL:

这是在带有 GCC 4.6.0(我编译的)的 MacOS X 10.6.7 上运行的。由于它与您所获得的基本相同,因此 G++ 的版本本质上是无关紧要的(但不是全部;Apple 与 GCC 4.2.1 一起分发的 c++filt 无法识别您提供的“nm”输出,即使在从文件中清除 BOM)。

好的 - 几根白发之后 - 我大致知道发生了什么。

当我运行 nm log.o , 它说 ' nm: no name list '.那是因为它实际上是一个空的目标文件。它是一个空目标文件,因为所有代码都在类声明中,但从未使用过,所以文件中没有目标代码,也没有函数。

我怀疑它与定义有关 - 我没想到它是完全“没有定义的函数”。

那么,我们该如何解决呢?

第一个问题是你有 log.cpp 但它不包含 log.h。这是一个强有力的问题指标。 header 定义源中定义的类的公共(public)接口(interface),确保它们一致的唯一(理智)方法是将 header 包含在源文件中。事实上,最好先包含 header ,这样您就可以确定它是自包含的(可以在任何源模块中使用)。

当我们这样做时,我们立即发现 log.h 不是独立的——它需要 #include <vector>也。修复后,我们发现您无法成功编译 log.cpp:

g++    -c -o log.o log.cpp
log.cpp:12:8: error: redefinition of ‘struct logResult’
log.h:15:8: error: previous definition of ‘struct logResult’
log.cpp:17:8: error: redefinition of ‘struct parsedLog’
log.h:20:8: error: previous definition of ‘struct parsedLog’
log.cpp:22:7: error: redefinition of ‘class Log’
log.h:25:7: error: previous definition of ‘class Log’
make: *** [log.o] Error 1

这两个结构已在 header 中声明,因此不应在源代码中重新声明。函数定义必须以 Log::为前缀,并从“class Log { ... }”大括号中移除。然后例行清理编译错误,导致:


日志.h

#ifndef LOG_H_
#define LOG_H_

#include <vector>
#include <string>
using namespace std;

struct logResult {
    vector <string> result;
    int status;
};

struct parsedLog {
    string result;
    int status;
};

class Log {
public:
    int initialize();
    int initialize(string text);
    Log ();
    Log (string text);
    bool isInitialized();
    int add(string text);
    int operator+= (string text);
    int clearLog (bool init = true);
    logResult getLog();
    parsedLog getLog(string delim);
private:
    bool initialized;
    vector <string> actionLog;
};

#endif /* LOG_H_ */

日志.cpp

#include "log.h"
#include "consts.h"
using namespace std;

int Log::initialize(){
    if (initialized) return ALREADY_INIT;
    actionLog.push_back("*** Log initialized ***");
    initialized = true;
    return SUCCESS;
}
int Log::initialize(string text){
    if (initialized) return ALREADY_INIT;
    // otherwise...
    initialize();
    actionLog.push_back("Initialization message: "+text);
    return SUCCESS;
}
Log::Log (){
    initialize();
}
Log::Log (string text){
    initialize(text);
}
bool Log::isInitialized(){
    return initialized;
}
int Log::add(string text){
    if (!initialized) return NOT_INIT;
    actionLog.push_back(text);
    return SUCCESS;
}
int Log::operator+= (string text){
    return add(text);
}
int Log::clearLog(bool init){
    if (!initialized) return NOT_INIT;
    //delete actionLog;
    initialized = false;
    if (init) return initialize();
    // Else
    return SUCCESS;
}
logResult Log::getLog(){
    if (!initialized){
        logResult final;
        final.status = NOT_INIT;
        return final;
    } else {
        logResult final;
        final.result = actionLog;
        final.status = SUCCESS;
        return final;
    }
}
parsedLog Log::getLog(string delim){
    if (!initialized){
        parsedLog final;
        final.status = NOT_INIT;
        return final;
    } else {
        parsedLog final;
        string logString;
        for (unsigned int i; i<actionLog.size()-1; i++){
            logString += actionLog[i];
            logString += delim;
        }
        logString += actionLog.back();
        final.result = logString;
        final.status = SUCCESS;
        return final;
    }
}

这些文件可以干净地编译生成包含一些有用函数的 log.o。之后的链接失败是:

Undefined symbols for architecture x86_64:
  "Building::Building(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
      runUI()    in ui.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

修复该问题留给您作为练习 - 但我相信在 building.h 和 building.cpp 中需要进行类似的更改。


还有一些问题需要解决。特别是, header 通常不应该做 using namespace std;因为这是对其他程序员对他们使用的 namespace 的控制的无端入侵。参见 Using namespace in C++ headers有关此问题的最近讨论。

关于eclipse - ld : Symbol(s) not found… but they are there…,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5864282/

相关文章:

android - adb 服务器已过期。杀死...无法绑定(bind) 'tcp:5037' ADB 服务器没有确认 * 无法在 ubuntu 14.04 LTS 中启动守护进程 *

java - 使用 eclipse 在 Windows 上运行 .sh(来自 linux)脚本

java - eclipse调用数据库错误

c++ - 在 visual studio 2012 中使用 Log4cxx

java - Eclipse javadoc 覆盖插件

javascript - "window.frame.openDialog"无法在 Mac OS X 中选择文件

css - Safari + jQuery thickbox = 巨大的视觉故障?

macos - -mouseMoved OSX 不会在 Sprite 套件 SKScene 中被调用

C++ 模板,链接错误

build - CMake 将来自不同 CMakeLists.txt 的对象附加到一个库中