C++ 段错误 访问对象指针向量的 std::vector.size()
C++ segfault when accessing std::vector.size() of an objects pointer's vector
我在执行代码时有一个段错误:根据GDB,段错误由
Program received signal SIGSEGV, Segmentation fault.
0x00000000004090a6 in std::vector<GeometricObject*, std::allocator<GeometricObject*> >::size (this=0x30)
at /usr/include/c++/4.9/bits/stl_vector.h:655
655 { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
这是 GDB 的输出,其中命令
#0 0x000000000040923c in std::vector<GeometricObject*, std::allocator<GeometricObject*> >::size (
this=0x30) at /usr/include/c++/4.9/bits/stl_vector.h:655
#1 0x000000000040843c in World::hitObjects (this=0x0, r=...)
at /mnt/7DEB96B84D6B013D/Universita/Programmazione ad oggetti e grafica/esercizi/Progetto - RTFGU/core/world/world.cpp:85
#2 0x000000000040a0d8 in MultipleObjects::traceRay (this=0x67ea70, r=...)
at /mnt/7DEB96B84D6B013D/Universita/Programmazione ad oggetti e grafica/esercizi/Progetto - RTFGU/core/tracers/multipleObjects.cpp:13
#3 0x00000000004086f0 in World::renderScene (this=0x7fffffffdd60)
at /mnt/7DEB96B84D6B013D/Universita/Programmazione ad oggetti e grafica/esercizi/Progetto - RTFGU/core/world/world.cpp:115
#4 0x0000000000407c05 in main (argc=1, argv=0x7fffffffdea8)
at /mnt/7DEB96B84D6B013D/Universita/Programmazione ad oggetti e grafica/esercizi/Progetto - RTFGU/main.cpp:20
这是主要类
int main(int argc, char const *argv[]){
World w;
w.build();
w.renderScene();
w.displayImage();
return 0;
}
这里有世界级的定义
class World{
public:
World();
~World();
void addObject(GeometricObject *);
void build();
ShadeRec hitObjects(const Ray &);
void renderScene() const;
void displayImage() const;
void displayPixel(const int, const int, const RGBColor &) const;
RGBColor backgroundColor;
ViewPlane vp;
Tracer * tracer_ptr;
cv::Mat * rendering;
std::vector<GeometricObject*> objects;
};
// definitions
World::World(): backgroundColor(), vp(), tracer_ptr(0), rendering(0), objects(){}
World::~World(){}
void World::addObject(GeometricObject * o){
objects.push_back(o);
}
void World::build(){
std::cout << "Build begins" << std::endl;
int width = 1024, height = 768;
vp.setHres(width);
vp.setVres(height);
vp.setPixelSize(1.f);
vp.setGamma(1.f);
rendering = new cv::Mat(height,width, CV_8UC3, cv::Scalar(0,0,0));
tracer_ptr = new MultipleObjects(this);
backgroundColor = BLACK;
Sphere * s1 = new Sphere(Point(0., -25., 0.), 80., CYAN);
Sphere * s2 = new Sphere(Point(0.,30.,0.), 60., MAGENTA);
Plane * p = new Plane(Point(0.), Normal(0., 1., 1.), YELLOW);
std::cout << objects.size() << std::endl; // used for debug: size is 0
addObject(s1);
addObject(s2);
addObject(p);
std::cout << objects.size() << std::endl; // used for debug: size is 3
for(uint i = 0; i < objects.size(); i++) // in this scope objects.size() works
std::cout << objects[i]->toString() << std::endl;
// at this stage gdb give me these information:
(gdb) p this
$1 = (World * const) 0x7fffffffdd60
(gdb) p *this
$2 = {backgroundColor = {r = 0, g = 0, b = 0}, vp = {hRes = 1024, vRes = 768, s = 1, gamma = 1,
gammaInv = 1}, tracer_ptr = 0x67ea70, rendering = 0x67d870,
objects = std::vector of length 3, capacity 4 = {0x67ea90, 0x67ead0, 0x67eb10}}
(gdb) p &objects
$4 = (std::vector<GeometricObject*, std::allocator<GeometricObject*> > *) 0x7fffffffdd90
}
ShadeRec World::hitObjects(const Ray & r){
// at this stage , instead
(gdb) p this
$1 = (World * const) 0x0
(gdb) p *this
Cannot access memory at address 0x0
(gdb) p objects
Cannot access memory at address 0x30
(gdb) p &objects
$2 = (std::vector<GeometricObject*, std::allocator<GeometricObject*> > *) 0x30
std::cout << "hitObjects begins" << std::endl;
ShadeRec sr(*this);
int objNum = objects.size(); // in this scope objects.size() throw a segfault
double t, tmin = viewLimit;
for(int i = 0; i < objNum ; i++){
if(objects.at(i)->hit(r, t, sr) && t < tmin){
sr.haveHit = true;
sr.color = objects.at(i)->getColor();
tmin = t;
}
}
return sr;
}
void World::renderScene() const{
std::cout << "renderScene begins" << std::endl;
RGBColor col;
Ray ray;
double z = 10;
double x, y;
ray.d = Vect3(0.,0.,-1.);
for(int r = 0; r < vp.vRes; r++)
for(int c = 0; c < vp.hRes; c++){
x = vp.s*(c-(vp.hRes-1)*.5);
y = vp.s*(r-(vp.vRes-1)*.5);
ray.o = Point(x, y, z);
std::cout << "debug - " << r << " " << c << std::endl;
col = tracer_ptr->traceRay(ray);
std::cout << "exit traceRay" << std::endl;
rendering->at<cv::Vec3b>(cv::Point(c,r)) = cv::Vec3b(col.b*255,col.g*255,col.r*255);
}
}
void World::displayImage() const{
cv::imwrite("rendering.png", *rendering);
cv::namedWindow("Rendering", cv::WINDOW_AUTOSIZE );
if(!rendering->empty())
cv::imshow("Rendering", *rendering);
cv::waitKey(0);
}
最后是 MultipleObject 类,它启动 traceRay() 在 world::renderScene() 中并调用 world::hitObject() 本身
class MultipleObjects: public Tracer{
public:
MultipleObjects();
MultipleObjects(World *);
~MultipleObjects();
RGBColor traceRay(const Ray &) const;
protected:
World * world_ptr;
};
// definitions
MultipleObjects::MultipleObjects(): Tracer(){}
MultipleObjects::MultipleObjects(World * w): Tracer(w){}
MultipleObjects::~MultipleObjects(){}
RGBColor MultipleObjects::traceRay(const Ray & r) const{
ShadeRec sr(world_ptr->hitObjects(r));
if(sr.haveHit)
return sr.color;
else
return world_ptr->backgroundColor;
}
问题是:为什么在 World::build() 作用域中所有工作,而在 World::hitObjects() 中,这指向 NULL 而 &objects 指向0x30?
提前感谢您的回答,对不起我的英语不好,最终是我的第一个问题。
看起来你的世界指针无效。
如果你允许你的 MultipleObjects 类(也就是没有世界指针)的僵尸状态,你至少可以做的是将world_ptr初始化为 nullptr 并在尝试调用它的任何内容之前对其进行检查。
我发现扩展Tracer类的
MultipleObjects类除了Tracer继承的变量之外,还有一个World * world_ptr变量。所以当我打电话时:
tracer_ptr = new MultipleObjects(this);
Tracer's World* var 被设置为 this,将 MultipleObjects's World* var 留空。
相关文章:
- 使用std::vector的OpenCL矩阵乘法
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- std::vector的包装器,使数组的结构看起来像结构的数组
- 编译器如何区分std::vector的构造函数
- 使用 pqxx 将 std::vector 存储在 postgresql 中,并从数据库中检索它
- 在std::vector上存储带有模板的类实例
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 为什么std::vector比数组慢
- std::vector::迭代器是否可以合法地作为指针
- 如何将二进制格式的 C++ 对象的 std::vector 保存到磁盘?
- 为什么std::vector和std::valarray初始化构造函数不同
- ";结果类型必须是可从输入范围的值类型""构造的;创建std::vector时
- 在没有未定义行为的情况下实现类似std::vector的容器
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 如何将AERT_Allocate与 std:vector 一起使用
- 推导 std::vector::back() 的返回类型
- 如何将原始字节附加到 std::vector?
- std::vector 没有重载函数的实例与参数列表匹配
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?