我这样定义了一个名为 nth_best_parse 的类:
class nth_best_parse {
public:
int traversal;
int nth_best_active;
int nth_best_passive;
double viterbi_prob;
nth_best_parse();
nth_best_parse(int t, int nbl, int nbr, double v) {traversal = t; nth_best_active = nbl; nth_best_passive = nbr; viterbi_prob = v;}
};
然后我将这个 nth_best_parse 的 vector 声明为两个不同类的成员:
class Edge { // an edge associates an Earley style dotted-item with a span
public:
<some irrelevant stuff>
Span span; // Span of the edge
bool isActive;
vector<Traversal *> leading_traversals; // The list of traversals which lead to parsing of this edge
vector<nth_best_parse> n_best_parses;
union {
DottedRule rule_state; // Accessed if isActive is true
int symbol; // Accessed if isActive is false
// A symbol corresponding to the category of a passive edge
// Put inside this union to save space
};
inline int span_length() {return span.end - span.start;}
};
<some other stuff>
class BPCFGParser {
public:
// Some data structures used in intermediary computations for calculating the n-best parses
// vector<vector<int> > nth_best_pairs;
vector<vector<nth_best_parse> > n_best_pairs_for_traversals;
<some other stuff>
void compute_n_best_parses(Edge *e, int n);
<some other stuff>
}
然后我用 gdb 运行这个程序(顺便说一下,我使用的是 Linux Ubuntu 9.04、g++ 4.3.3、GNU gdb 6.8-debian)并在 compute_n_best_parses() 定义的末尾设置断点条件(为了找到我想要的这个函数的确切调用,我从一个段错误中追溯)。当 gdb 遇到断点时,我发出了一组命令,gdb 输出如下:
(gdb) print e->n_best_parses.size()
$27 = 1
(gdb) print e->n_best_parses[0]
$28 = (nth_best_parse &) @0x1e96240: {traversal = 0, nth_best_active = 0, nth_best_passive = 0, viterbi_prob = 0.16666666666666666}
(gdb) print e->n_best_parses[0].traversal
$29 = 0
(gdb) print &(e->n_best_parses[0].traversal)
$30 = (int *) 0x1e96240
(gdb) awatch *$30
Hardware access (read/write) watchpoint 6: *$30
(gdb) print e->n_best_parses
$31 = {<std::_Vector_base<nth_best_parse, std::allocator<nth_best_parse> >> = {
_M_impl = {<std::allocator<nth_best_parse>> = {<__gnu_cxx::new_allocator<nth_best_parse>> = {<No data fields>}, <No data fields>},
_M_start = 0x1e96240, _M_finish = 0x1e96258, _M_end_of_storage = 0x1e96288}}, <No data fields>}
(gdb) continue
Continuing.
Hardware access (read/write) watchpoint 6: *$30
Old value = 0
New value = 1
0x0000000000408a4c in __gnu_cxx::new_allocator<nth_best_parse>::construct<nth_best_parse> (this=0x1e96208, __p=0x1e96240, __args#0=@0x7fff8ad82260)
at /usr/include/c++/4.3/ext/new_allocator.h:114
114 { ::new((void *)__p) _Tp(std::forward<_Args>(__args)...); }
(gdb) backtrace
#0 0x0000000000408a4c in __gnu_cxx::new_allocator<nth_best_parse>::construct<nth_best_parse> (this=0x1e96208, __p=0x1e96240, __args#0=@0x7fff8ad82260)
at /usr/include/c++/4.3/ext/new_allocator.h:114
#1 0x000000000042169c in std::vector<nth_best_parse, std::allocator<nth_best_parse> >::push_back<nth_best_parse> (this=0x1e96208, __args#0=@0x7fff8ad82260)
at /usr/include/c++/4.3/bits/stl_vector.h:703
#2 0x0000000000402bef in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f5492858b78, n=3) at BPCFGParser.cpp:639
#3 0x00000000004027fd in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f5492859d58, n=3) at BPCFGParser.cpp:606
#4 0x00000000004027fd in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f549285a1d0, n=3) at BPCFGParser.cpp:606
#5 0x00000000004064d8 in main () at experiments.cpp:75
BPCFGParser.cpp 的第 639 行是这样的:
PUSH_BEST_PAIR_FOR_TRAVERSAL(i,row,column,grammar->probs[temp_rule.symbol][temp_rule.expansion]);
这是一个在文件开头定义的宏:
#define PUSH_BEST_PAIR_FOR_TRAVERSAL(x,y,z,t) n_best_pairs_for_traversals[x].push_back(nth_best_parse(x, y, z, e->leading_traversals[x]->active_edge->n_best_parses[y].viterbi_prob * e->leading_traversals[x]->passive_edge->n_best_parses[z].viterbi_prob * t))
顺便说一下,Traversal 类定义为:
class Traversal { // Class for a traversal
public:
Edge *active_edge;
Edge *passive_edge;
Traversal();
Traversal(Edge *a, Edge *p) {active_edge = a; passive_edge = p;}
};
所以实际上我正在向 vector n_best_pairs_for_traversals 推送一些东西,它是类 BPCFGParser 的一个实例的成员,而 push_back() 代码以某种方式覆盖了 vector n_best_parses,它是类 Edge 的一个实例的成员.这怎么可能?
最佳答案
你显然在某处存在内存损坏问题。
但是这里没有足够的信息来帮助你。
但是您正在编写 C++ 代码并且您的类包含指针。
这不是一个好兆头(C++ 类中几乎不应该有 RAW 指针)。
对于没有经验的 C++ 开发人员来说,这也常常是内存损坏的原因!
你有遵守4的规则吗?
确保每个类都包含 RAW 拥有的指针:
- 构造器
- 拷贝构造函数
- 赋值运算符
- 析构函数。
关于C++ vector push_back() 覆盖另一个相同类型的 vector ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2008599/