gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-05 04:18:58 26 4
gpt4 key购买 nike

我的项目最近真的很糟糕——我解决了一大堆错误,然后它抛出了一个神秘的 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com