过去几个小时我一直试图通过我的调用堆栈来解决这个问题,并且仍然没有弄明白发生了什么!
我的序列数据库基本上收集文件所需的信息,然后调用我的Linked List类创建一个带有收集信息的新节点,并将该节点放在链接列表的末尾:
部首:
#ifndef SEQUENCE_H
#define SEQUENCE_H
#include "DNA.h"
#include "DNAList.h"
class SequenceDatabase
{
public:
//Default Constructors
SequenceDatabase();
//Methods
void importEntries(string);
private:
DNAList list;
};
#endif
来源:
#include "SequenceDatabase.h"
#include "DNA.h"
#include "DNAList.h"
#include <fstream>
using namespace std;
SequenceDatabase::SequenceDatabase() //Default Constructor.
{
DNA object;
DNAList list;
}
void SequenceDatabase::importEntries(string name)
{
DNA* item;
ifstream file;
file.open(name);
if(!file.is_open())
{
cout << "Error opening file!" << endl;
exit(1);
}
char letter;
string label, sequence;
int ID, length, index;
file >> letter;
if(letter == 'D' || letter == 'd')
{
file >> label >> ID >> sequence >> length >> index;
DNA object(label,ID,sequence,length,index);
item = &object;
DNAList list(item);
}
}
我的链接列表标题文件:
class DNAList
{
public:
//Constructors
DNAList();
DNAList(DNA* newDNA);
//Linked List Functions
void push_back(DNA* newDNA);
DNA* findID(int ID);
void obliterate(int ID);
//DNANode struct for Linked List
struct DNANode
{
DNA* data;
DNANode* next;
DNANode* prev;
};
private:
DNANode* head;
typedef DNANode * ptr;
};
#endif
我的链接列表类源文件:
#include "DNAList.h"
#include "SequenceDatabase.h"
#include "DNA.h"
#include <iostream>
using namespace std;
DNAList::DNAList()
{
head = NULL;
}
DNAList::DNAList(DNA* newDNA)
{
cout <<"In DNA list second constructor" << endl;
ptr cur;
if(head == NULL)
{
ptr newNode = new DNANode;
cur = newNode;
cur -> data= newDNA;
head = cur;
cur -> prev = head;
cur -> next = NULL;
}
else
{
push_back(newDNA);
}
}
void DNAList::push_back(DNA* newDNA)
{
ptr cur;
ptr last;
cout << "Note: Adding " << newDNA -> getID() << " ..." << endl;
ptr newNode = new DNANode;
cur = head;
while(cur != NULL)
{
last = cur;
cur = cur -> next; //ERROR IS HAPPENING AT THIS LINE.
}
newNode -> data = newDNA;
newNode -> prev = last;
newNode -> next = NULL;
cur = newNode;
}
现在,我是新手使用类来包含我的链表,所以我不确定我的节点结构是否应该在我的Linked List类的公共或私有内存中,以及我的构造函数是否按照它们应该的方式定义是。 Node结构基本上是指向名为DNA的头文件中的实际数据的指针,其中包含指向我的下一个和前一个节点的结构的附加指针,以便数据永远不会被搞乱,但只是指向。
错误被卡在我的链接列表源文件中的push_back函数中间的行上。我给它贴了标签。请有人可以分享我在这里做错了什么吗?谢谢!
我的主要档案:
#include <iostream>
using namespace std;
#include "sequenceDatabase.h"
int main(){ //int argc, char* argv[]){
string commandsFileName;
commandsFileName = "lab1-commands-short.tab"; // for initial development
//commandsFileName = "lab1-commands.tab";
// commandsFileName = "lab1-commands-test.tab"; // for testing & grading
SequenceDatabase entries;
cout << "Importing " << commandsFileName << endl;
entries.importEntries(commandsFileName);
return 0;
}
答案 0 :(得分:4)
if (...)
{
DNA object(label, ID, sequence, length, index);
item = &object;
DNAList list(item);
}
object
是一个本地范围的对象,意味着它在块的结束括号中被销毁。您将item
设置为指向该本地对象,并将其发送至DNAList
的构造函数。问题是,如果您在销毁后尝试访问object
,您的程序将不再处于有效状态。这是因为一旦你的对象被销毁,指向它的对象将被留下作为悬空指针。访问悬空指针之类的事情称为未定义行为。
但那不是你UB的来源(还)。真正的问题出在你的DNAList
构造函数中:
if (head == NULL)
{
// ...
}
else
{
push_back(newDNA);
}
head
是一个未初始化的指针。声明但未定义的原始对象(如int
,char
,char*
)未初始化,因此具有不确定的值。在此状态下测试对象,就好像它们具有值一样,也是Undefined Behavior。
请注意,UB仍然可以使您的代码正常工作。但它也可以做其他在你的程序中没有逻辑意义的令人讨厌的事情。
head
具有此时存储在堆栈中的任何值,可能不是0.因此条件失败并调用push_back()
。
然后在while循环中执行cur->next
取消引用未初始化的指针,最后导致抛出异常。
可以通过在head
的构造函数体内设置NULL
到DNAList
并动态分配object
来避免特定的运行时错误(因此它存在于超出范围的范围内) if
语句,但在评论中指定的程序中还有一些不正确的内容。