问题描述
使用VTK写项目时,有时候总报错在Render()行。
说发生访问冲突,然后给一段冲突的地址。
有时是这个,有时是0XFFFFFFFFFFFFFF这种系统内存。
重启VS或重启电脑之后,问题依旧存在,困扰了很久。可能有几个月。。。
主要是他是偶发的BUG,不一定会遇到,可能隔一周给你来一次,然后放着不管写别的代码去了,然后过一会运行又没了,让人摸不着头脑,很玄学。
踩坑之路
其实也能猜到。这种错误肯定是内存,指针之类的问题。
我一开始放着没管,因为他大概过半小时之后再运行,就不报错了。。。
而且之后都不会再报错。
后面实在受不了了,,我开始找写的有指针的代码。
只有一个读数据的指针,以为是自己没有free()掉自己读的数据。
于是把写在main()最后面的free写在读到vtk数据之后,类似这种
int main(){
FILE* fp = fopen("./Data/test.bin","rb");
UINT8* pInputData = (UINT8*)malloc(volsize);
fread(pInputData,sizeof(UINT8),volsize,fp);
fclose();
...
vtkNew<vtkImageData> pImagedata;
//从imageimport读取到vtkImageData数据
pImagedata.deepcopy(imageimport->getoutput());
free(pInputData);
...
renwin->Render();
//本来写在main结束的free 写在deepcopy之后了
}
之后运行,还真不报错了。
但是后面注释掉那行free(),重新运行多次,仍然不报错。
这就很奇怪了,感觉我free加第一次有用,后面怎么弄都没用了。
然后又过了几天,我直接用vtk的类读一个demo,没用自己的指针读。类似这种
int main(){
vtkSmartPointer<vtkMetaImageReader> reader = vtkSmartPointer<vtkMetaImageReader>::New();
reader->setFileName("./brain.mhd");
reader->update();
...
renwin->Render();
//运行Render也报错。。
}
然后运行也报错,感觉和我的free根本没关系啊。
解决
今天一跑代码又tm遇到了,受不了到要写博客的地步了。
在彻底检查代码,阅读VTK源码,vtk交流群里问大佬之后,我感觉是智能指针的原因。
因为我中间有段代码是类似这样的
void SetProperty(vtkSmartPointer<vtkVolumeProperty> property){
...
//设置一些透明度,颜色之类的
}
int main(){
...
vtkSmartPointer<vtkVolumeProperty> prop = vtkSmartPointer<vtkVolumeProperty>::New();
SetProperty(prop);
...
renwin->render();
}
在main里面我创建render,renwin这些进行渲染,但我用写了一个函数调用,在里面设置了体数据渲染的Property。
把此函数参数改成普通指针。运行就正常了。
void SetProperty(vtkVolumeProperty* property){
...
}
因为我在main函数内用智能指针创建一个对象,在main范围内,以及转为普通普通指针往函数传递的时候都没问题。
但是如果传递函数参数是智能指针,会执行拷贝构造函数,将智能指针相互赋值,然后函数参数的智能指针在函数返回堆栈时,将我在main里面传值的智能指针对象释放了。
这样就在Render的时候,发现渲染过程中需要访问已经被销毁的对象。出现访问冲突。
所以感觉这就是问题的根源!欢迎大佬指正我的理解。
总结
主要是网上搜到的资源都是说什么智能指针能自动管理生命周期,能用智能指针的地方全用智能指针,就不会有内存泄漏。
但我这是还没用完,就给释放的问题。
这篇讲C++智能指针的文章写的很好: https://blog.csdn.net/cpp_learner/article/details/118912592
里面提到了,不要把智能指针相互赋值的问题。特别是禁止用任何类型智能指针get 函数返回的指针去初始化另外一个智能指针!
现在想想,这样函数传参确实使用了多个智能指针,并且相互赋值了。
苟GPT让我这样写的。。。