我正在尝试用c ++实现后缀树 在向我的向量列表添加节点时,它会在向树中添加第三个元素后抛出std :: bad_alloc。我不知道为什么会在第三次之后发生,你能帮我解决这个bad_alloc错误吗?
这是我的代码:
suffix_tree.cpp
#include <iostream>
#include <fstream>
#include <cmath>
#include <sstream>
#include <string>
#include <cstring>
#include "node.h"
using namespace std;
Node build_suffix_tree(string text){
Node root = Node();
int n = text.length();
int count;
Node * currentNode = &root;
Node tmpNode;
string suffix;
int suffixLen;
for(int i=0; i<n; i++){
suffix = text.substr(i,n);
suffixLen = suffix.length();
count = 1;
currentNode = &root;
while(count <= suffixLen){
cout << suffix << endl;
int pos = -1;
// bad_alloc occurs here
(*currentNode).addFils(Node(suffix[0], vector<Node>(), i));
cout << currentNode->getFils().size() << endl;
currentNode = ¤tNode[currentNode->getFils().size() - 1];
suffix = suffix.substr(1,suffixLen);
count++;
}
cout << " " << endl;
}
return root;
}
int main(){
string text = "helloeveryone";
Node root = build_suffix_tree(text);
return 0;
}
node.cpp
#include <string>
#include <vector>
#include "node.h"
using namespace std;
Node::Node(){
c = ' ';
fils = vector<Node>();
pos = -1;
}
Node::Node(char t, vector<Node> l, int p){
c = t;
fils = l;
pos = p;
}
void Node::addFils(Node n){
fils.push_back(n);
}
char Node::getString(void){
return c;
}
vector<Node> Node::getFils(){
return fils;
}
void Node::setFils(vector<Node> l){
fils = l;
}
node.h
#include <string>
#include <vector>
#ifndef NODE_H
#define NODE_H
class Node
{
public:
char c;
std::vector<Node> fils;
int pos;
Node();
Node(char c, std::vector<Node> fils, int p);
void addFils(Node n);
char getString(void);
std::vector<Node> getFils();
void setFils(std::vector<Node>);
};
#endif // NODE_H
生成文件
CC=g++
CFLAGS= -g
LDFLAGS=
EXEC=suffix_tree
all: $(EXEC)
suffix_tree: suffix_tree.o node.o
$(CC) -o suffix_tree suffix_tree.o node.o $(LDFLAGS)
node.o: node.cpp
$(CC) -o node.o -c node.cpp $(CFLAGS)
suffix_tree.o: suffix_tree.cpp node.h
$(CC) -o suffix_tree.o -c suffix_tree.cpp $(CFLAGS)
clean:
rm -rf *.o
mrproper: clean
rm -rf $(EXEC)
提前致谢。
答案 0 :(得分:5)
正如Nemanja Boric在评论中指出的那样,你正在覆盖你的筹码,所以任何事情都可能发生。在我的电脑上,它恰好是GCC中的bad_alloc
和clang中的普通段错误。
仔细观察这一行:
currentNode = ¤tNode[currentNode->getFils().size() - 1];
currentNode
是指向Node
的指针。在开始时,它指向在堆栈上分配的变量root
。
在第一次迭代中,它变为¤tNode[1 -1]
,等于currentNode
。所以没有任何事情发生(这不是我想的)。
在下一次迭代中,它会更改为¤tNode[2 - 1]
,等于¤tNode[1]
,等于currentNode+1
。这是堆栈上的一个地址,就在root
变量之后。它已分配,但它的值不是Node*
!它可以属于int n;
,但它可能完全不同,基于编译器优化。
在3.迭代中,当您尝试将此地址用作Node
实例(不是)时,您将获得未定义的行为,并且它们确实会发生任何事情。它可以杀死你的猫并烧毁你的房子。所以你仍然很幸运,只能获得bad_alloc
。
答案 1 :(得分:1)
错误的分配是因为堆栈/堆已经损坏,所以错误应该在你指出的代码行之前发生。
count== suffixLen
时发生错误。下面是代码中的代码片段,我们假设'suffix'是'ab',所以'suffixLen'是2。
在第一个循环之后,count为2,'suffix'为'b',在第二个循环中,代码
suffix = suffix.substr(1,suffixLen);
将失败并导致内存问题,因为1超出范围。因此,当'suffix'中只剩下一个字符时,你应该处理案例
suffixLen = suffix.length();
count = 1;
currentNode = &root;
while(count <= suffixLen){
// bad_alloc occurs here
(*currentNode).addFils(Node(suffix[0], vector<Node>(), i));
suffix = suffix.substr(1,suffixLen);
count++;
}
答案 2 :(得分:1)
这是非常错误的。
currentNode = ¤tNode[currentNode->getFils().size() - 1];
我的猜测是你希望将currentNode指针移动到列表的下一个元素。但是,您尚未分配列表。您将root初始化为Node,然后将currentNode指向root。除了root + sizeof(Node)之外没有分配的内存,它实际上存在于堆栈中,但这是无关紧要的,因为如果你做了新的Node(),就会发生同样的问题。
我认为你认为root是某种矢量或预分配列表,但我无法确定你的意图是什么。第一次迭代,currentNode-&gt; getFils()。size()返回1并且1-1 = 0,因此,currentNode将其指针设置为自身。在下一次迭代中,currentNode将自己设置为超出root的一个sizeof(Node)的内存位置,该位置处于未知区域。
答案 3 :(得分:1)
正如Nemanja Boric指出的那样,问题在于:
currentNode = ¤tNode[currentNode->getFils().size() - 1];
在每次迭代中,你都在调用currentNode的复制构造函数,堆栈中的内存地址会在每一步(currentNode,currentNode + 1,currentNode + 2等)上增加,通过这样做,你就会破坏{{ 1}},当你尝试push_back一个元素时,你会得到Node.fils
另一方面,如果要向bad_alloc
添加新元素,为什么需要增加对节点的引用?可能是你想使用链表吗?
答案 4 :(得分:0)
使用push_back()时我遇到了同样的问题。问题是向量需要在你的内存上有一个连续的空间来工作,并且由于你的操作系统在片段中分配内存,它可能会分配一个可能无法包含你的所有向量的空间。但是如果你知道矢量的最终大小,你可以使用std :: vector :: resize()来帮助你选择一个最好的位置来分配你的矢量。