Hi, We recently got a strange crash behavior in our software. We were fixing a piece of code that caused GL_ERRORS on some platforms. When we had fixed this, a new bug surfaced in a completely different part of the code base. It was code that had worked for years, but suddenly it started to make our software crash. I was able to solve the problem, but I had problem understanding why it started to crash all out of a sudden. So I tried to reduce the bug to a smaller working set.
The crash results from a null pointer exception in operator() inside TemplateAttributeDispatch in ArrayDispachers.cpp. See attached example for code that crashes when the variable: useCrashProneWayOfSettingVertexColor is set to TRUE. At first I though the problem was that we had multiple geometry sharing the same vertex color array. But that was not the problem. The problem was the way we changed the colors in the array. The old (and previously working) way of doing it was to use a node callback on the geode and in that callback clear and then fill the array with new values. (But this is the version that started to crash). So we changed the callback to iterate over the color array and changing the values instead. But I still have a bit of a problem with understanding why the first alternative would not work? Clearing and refilling the color array inside a node callback should be safe, but apparently not? /Björn ------------------ Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=59617#59617
#include <osg/Geometry> #include <osg/PositionAttitudeTransform> #include <osgViewer/Viewer> #include <ctime> class ColorCallback : public osg::NodeCallback { public: ColorCallback() {}; virtual void operator() (osg::Node* node, osg::NodeVisitor* nv) { osg::ref_ptr<osg::Geode> geode = node->asGeode(); if (geode) { osg::ref_ptr<osg::Geometry> geometry = geode->getDrawable(0)->asGeometry(); if (geometry) { time_t currentTime; time(¤tTime); int colorId = currentTime % 3; osg::Vec4 color = osg::Vec4(1.0, 1.0, 1.0, 1.0); if (colorId == 0) { color = osg::Vec4(1.0, 0.0, 0.0, 1.0); } else if (colorId == 1) { color = osg::Vec4(0.0, 1.0, 0.0, 1.0); } else { color = osg::Vec4(0.0, 0.0, 1.0, 1.0); } osg::ref_ptr<osg::Vec4Array> colorArray = dynamic_cast<osg::Vec4Array*>(geometry->getColorArray()); if (colorArray) { // Change below variable to toggle between working and crash prone version bool useCrashProneWayOfSettingVertexColor = true; if (useCrashProneWayOfSettingVertexColor) { colorArray->clear(); colorArray->push_back(color); geometry->setColorArray(colorArray); geometry->setColorBinding(osg::Geometry::BIND_OVERALL); colorArray->dirty(); } else { for(osg::Vec4Array::iterator cIt = colorArray->begin(); cIt != colorArray->end(); ++cIt) { (*cIt) = color; } } } } } traverse(node, nv); } private: }; int main( int argc, char **argv ) { osg::ArgumentParser arguments(&argc,argv); osg::ref_ptr<osg::Vec4Array> colorArray1 = new osg::Vec4Array; colorArray1->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0)); osg::ref_ptr<osg::Vec4Array> colorArray2 = new osg::Vec4Array; colorArray2->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0)); osg::ref_ptr<osg::Geometry> geometry1 = new osg::Geometry; osg::ref_ptr<osg::Geometry> geometry2 = new osg::Geometry; osg::ref_ptr<osg::Vec3Array> vertexArray1 = new osg::Vec3Array; osg::ref_ptr<osg::Vec3Array> vertexArray2 = new osg::Vec3Array; osg::ref_ptr<osg::Vec3Array> normalArray1 = new osg::Vec3Array; osg::ref_ptr<osg::Vec3Array> normalArray2 = new osg::Vec3Array; vertexArray1->push_back(osg::Vec3(0.0, 0.0, 0.0)); vertexArray1->push_back(osg::Vec3(1.0, 0.0, 0.0)); vertexArray1->push_back(osg::Vec3(1.0, 0.0, 1.0)); vertexArray1->push_back(osg::Vec3(0.0, 0.0, 1.0)); normalArray1->push_back(osg::Vec3(0.0, -1.0, 0.0)); vertexArray2->push_back(osg::Vec3(0.0, 0.0, 0.0)); vertexArray2->push_back(osg::Vec3(1.0, 0.0, 0.0)); vertexArray2->push_back(osg::Vec3(0.5, 0.0, 1.0)); normalArray2->push_back(osg::Vec3(0.0, -1.0, 0.0)); geometry1->setVertexArray(vertexArray1); geometry1->setNormalArray(normalArray1); geometry1->setNormalBinding(osg::Geometry::BIND_OVERALL); geometry1->setColorArray(colorArray1); geometry1->setColorBinding(osg::Geometry::BIND_OVERALL); geometry1->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,vertexArray1->size())); geometry1->setUseDisplayList(false); geometry1->setUseVertexBufferObjects(true); geometry2->setVertexArray(vertexArray2); geometry2->setNormalArray(normalArray2); geometry2->setNormalBinding(osg::Geometry::BIND_OVERALL); geometry2->setColorArray(colorArray2); geometry2->setColorBinding(osg::Geometry::BIND_OVERALL); geometry2->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,vertexArray2->size())); geometry2->setUseDisplayList(false); geometry2->setUseVertexBufferObjects(true); osg::ref_ptr<osg::Geode> geode1 = new osg::Geode; geode1->addDrawable(geometry1); geode1->setUpdateCallback(new ColorCallback()); geode1->setDataVariance(osg::Object::DYNAMIC); osg::ref_ptr<osg::Geode> geode2 = new osg::Geode; geode2->addDrawable(geometry2); geode2->setUpdateCallback(new ColorCallback()); geode2->setDataVariance(osg::Object::DYNAMIC); osg::ref_ptr<osg::Group> root = new osg::Group; osg::ref_ptr<osg::PositionAttitudeTransform> pat1 = new osg::PositionAttitudeTransform; pat1->setPosition(osg::Vec3(1.0, 0.0, 0.0)); pat1->addChild(geode1); osg::ref_ptr<osg::PositionAttitudeTransform> pat2 = new osg::PositionAttitudeTransform; pat2->setPosition(osg::Vec3(-1.0, 0.0, 0.0)); pat2->addChild(geode2); root->addChild(pat1); root->addChild(pat2); osgViewer::Viewer viewer(arguments); viewer.setSceneData(root); return viewer.run(); }
_______________________________________________ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org