C ++ 벡터 push_back ()는 같은 유형의 다른 벡터에 덮어 쓰입니까?
-
18-09-2019 - |
문제
이 방법으로 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의 벡터를 두 가지 다른 클래스의 구성원으로 선언했습니다.
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))
그건 그렇고, 클래스 트래버스는 다음과 같이 정의됩니다.
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;}
};
실제로 벡터 N_BEST_PAIRS_FOR_TRAVERSALS에 무언가를 푸시하고 있습니다. 이는 클래스 BPCFGPARSER의 인스턴스의 구성원이며 PUSH_BACK () 코드는 클래스 에지 인스턴스의 구성원 인 벡터 N_BEST_PARSES에 대해 어떻게 든 덮어 쓰기입니다. 이것이 어떻게 가능할 수 있습니까?
해결책
당신은 당신이 당신의 매크로에 유효한 첫 번째 인수를 전달한다고 확신합니까? 어쩌면 당신은 할 때 한계를 벗어나고있을 것입니다 n_best_pairs_for_traversals[x]
왜냐하면 x
벡터 크기보다 큽니다.
다른 팁
당신은 분명히 어딘가에 기억 부패 문제가 있습니다.
그러나 여기에는 당신을 도울 수있는 정보가 충분하지 않습니다.
그러나 C ++ 코드를 작성하고 있으며 클래스에는 포인터가 포함되어 있습니다.
이것은 좋은 징조가 아닙니다 (C ++ 클래스에는 원시 포인터가 거의 없어야합니다).
이것은 또한 경험이없는 C ++ 개발자에게 메모리 손상의 원인이기도합니다!
4의 규칙에 순종 했습니까?
RAW 소유의 포인터가 포함 된 모든 수업을 확인하십시오.
- 건설자
- 생성자 복사
- 과제 연산자
- 폐물 소각로.
나는 당신이 벡터를 사용하여 객체를 저장하고 (아마도 트래버스가 될까요?), 새로운 요소를 해당 벡터에 밀면 이미 벡터의 요소로 포인터를 무효화 할 수 있다는 것을 깨닫지 못합니다. 이 경우 대신 Deque를 사용하십시오.