sor*_*ife 0 c++ pointers segmentation-fault
我有两个班级说A&B是这样的:
// A.h
#include <iostream>
#include <vector>
using namespace std;
#ifndef A_H_
#define A_H_
#include "B.h"
class A {
public:
std::vector<B> bVec;
A();
void foo();
virtual ~A();
};
#endif /* A_H_ */
//--------------------
// A.cpp
#include "A.h"
A::A() {
B b(this);
bVec.push_back(b);
}
void A::foo() {
for(int i=0; i<bVec.size(); i++)
bVec[i].addNewB();
}
A::~A() {
}
//--------------------
// B.h
#include <iostream>
#include <vector>
using namespace std;
#ifndef B_H_
#define B_H_
class A;
class B {
public:
A* parent;
double data[15];
B(A* p);
void addNewB();
virtual ~B();
};
#endif /* B_H_ */
//--------------------
// B.cpp
#include "B.h"
#include "A.h"
B::B(A* p) {
parent = p;
}
void B::addNewB() {
A* tmpA = parent;
if(parent->bVec.size() < 3)
{
std::cout<< "Before: " << parent->bVec.size() << '\n';
parent->bVec.push_back(B(parent));
std::cout<< "After: " << parent->bVec.size() << '\n';
}
if(tmpA == parent)
cout<< "parent the same\n";
else
cout<< "parent changed\n";
}
B::~B() {
}
//--------------------
// main.cpp
#include <stdio.h>
#include "A.h"
int main()
{
A a;
a.foo();
std::cout<< "finish\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时,我得到以下结果:
之前:1
之后:16276538888567495168
父母改变了
之前:2
之后:3
父母一样
父母一样
完
您可以看到的问题是,有时父指针会在push_back之后发生变化.我尝试在push_back之前和之后调试代码我检查了父指针.在此之前它是一些地址,但在此之后它是另外的东西加上这个文本:这似乎有一些分段错误.
这里问题的关键似乎是B的每个实例的大小.如果我将'data'的大小更改为低于14的任何值,程序工作正常但是14或更高时会发生这种情况.
这看起来非常奇怪,我花了几天时间与之斗争.你能告诉我为什么会这样吗?
void B::addNewB() {
A* tmpA = parent;
if(parent->bVec.size() < 3)
{
std::cout<< "Before: " << parent->bVec.size() << '\n';
parent->bVec.push_back(B(parent));
std::cout<< "After: " << parent->bVec.size() << '\n';
}
if(tmpA == parent)
cout<< "parent the same\n";
else
cout<< "parent changed\n";
}
Run Code Online (Sandbox Code Playgroud)
这里更改了bVec,其中包含运行代码this的特定B对象.
void A::foo() {
for(int i=0; i<bVec.size(); i++)
bVec[i].addNewB();
}
Run Code Online (Sandbox Code Playgroud)
bVec在此次通话中被更改.在push_back()超过预分配堆空间的调用(可能是这样的),vector需要重新分配堆内存并将所有内容移动.在移动过程中,vector销毁了B运行该代码的对象.控制已恢复到B过时的代码this,因此this->parent现在包含垃圾.
以下是回溯可能的样子:
A::foo()
B::addNewB()
vector<B>::reallocate() //destroys previous frame's B
Run Code Online (Sandbox Code Playgroud)