双指针指向同一内存的释放问题

1,问题

  写代码的时候遇到一个问题,在方法类里面有个成员变量IplImage* resultImageToDisp,在主函数里面有个局部变量IplImage* resultImage,我需要将resultImageToDisp赋值给resultImage,但只是浅拷贝,就是说resultImageToDisp和resultImag两个图像指针指向了同一内存,主函数结束时按惯例使用cvReleaseImage(&resultImage),但是在退出函数体时候调用方法类的析构函数,此析构函数也存在一个cvReleaseImage(&resultImageToDisp),这样就造成同一内存释放两次报错。本来简单以为在析构时添加一个if(resutlImageToDisp!=NULL)判断语句就可以解决问题,可是还是报错。那么问题来了,NULL的作用是什么,此处添加什么判断语句可以解决问题?

2,抽象

char *c1,*c2;
c1=new char[10];
c2=c1;
delete c1;
if(/*    c2指向的内存空间没有被释放    */)
{
delete c2;
}

  该问题抽象成以上一段代码,即寻找if判断语句。

3,思路

  首先,我想到的是判断指针是否为NULL。由于没能真正理解NULL的作用,想当然认为判断指针是否为NULL,就是判断该指针指向的内存是否为0,这是错误的理解。经过测试,我对同一指针加上NULL判断可以通过,如以下代码。

if (ROIImageUnsmoothed!=NULL)
{
   cvReleaseImage(&ROIImageUnsmoothed);
}
if (ROIImageUnsmoothed!=NULL)
{
   cvReleaseImage(&ROIImageUnsmoothed);
}

  

resultImage=resultImageToDisp;
cvReleaseImage(&resultImage);
if (resultImageToDisp!=NULL)
{
    cvReleaseImage(&resultImageToDisp);
}

 

  第一次if成立,第二次不成立,代码完全没问题。而对于双指针指向同一内存却报错,说明,NULL只是判断指针本身,而不是它的内存。

  查阅资料才明白,释放内存,如free(),deleate(),只是做了一件事情:斩断指针变量与这块内存的关系。(我觉得应该是将这块内存交还给系统,不再供程序使用)free函数就是把这块内存和指针之间的所有关系斩断。从此指针和那块内存之间再无瓜葛。至于指针变量本身保存的地址并没有改变,但是它对这个地址处的那块内存却已经没有所有权了。那块被释放的内存里面保存的值也没有改变,只是再也没有办法使用了。更斩草除根的办法是释放后马上悬空地址,即将指针置为NULL:将指针保存的地址清除,使其不指向任何内存。

  这样可以解释,opencv的cvReleaseImage函数,一定包括释放内存和指针悬空两个过程。释放掉resultImage后,该指针指向的内存已经不存在,但是并不影响resultImageToDisp,它任然是一个非NULL的指针,所以if判断语句会失败,而且它的指向内存已经不存在,所以再次释放会报错。

  最后,再次查阅资料,发现没有什么好的方法可以处理,囧。。。

4,收获

  养成好的习惯,指针变量创建时初始化,要么将指针设置为NULL,要么让它指向合法的内存。

  指针指向的内存被释放后,紧接着将指针置为NULL。

  别用两个指针指向同一内存这种邪恶的东西。

参考:

  http://bbs.csdn.net/topics/80162678

  http://www.cnblogs.com/haore147/p/3647437.html

转载于:https://www.cnblogs.com/yssongest/p/4608878.html

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果您希望实现一个静态函数,可以在其中使用类的成员,但函数指针不带参数,并且每次调用都指向不同的内块,可以使用lambda表达式和std::function来实现。以下是一个示例代码: ```cpp #include <iostream> #include <Windows.h> #include <functional> class CallbackClass { public: int memberVariable; static void StaticCallback() { // 获取类的实例指针 CallbackClass* instance = reinterpret_cast<CallbackClass*>(GetCallbackInstance()); // 使用类的成员 std::cout << "Member variable: " << instance->memberVariable << std::endl; } static void* GetCallbackInstance() { // 通过VirtualAlloc分配新的内存块来存储类的实例指针 LPVOID executableMemory = VirtualAlloc(NULL, sizeof(CallbackClass), MEM_COMMIT, PAGE_READWRITE); if (executableMemory == NULL) { std::cerr << "Failed to allocate executable memory!" << std::endl; return nullptr; } return executableMemory; } }; int main() { // 创建一个类对象并设置成员变量 CallbackClass instance1; instance1.memberVariable = 42; // 将类对象的指针保存在可执行的内存块中 void* callbackInstance1 = CallbackClass::GetCallbackInstance(); memcpy(callbackInstance1, &instance1, sizeof(CallbackClass)); // 创建一个函数对象(lambda表达式)并绑定静态回调函数 auto callback1 = []() { CallbackClass::StaticCallback(); }; // 调用静态回调函数 callback1(); // 创建另一个类对象并设置成员变量 CallbackClass instance2; instance2.memberVariable = 99; // 将新类对象的指针保存在可执行的内存块中 void* callbackInstance2 = CallbackClass::GetCallbackInstance(); memcpy(callbackInstance2, &instance2, sizeof(CallbackClass)); // 创建另一个函数对象(lambda表达式)并绑定静态回调函数 auto callback2 = []() { CallbackClass::StaticCallback(); }; // 调用另一个静态回调函数 callback2(); // 释放内存 VirtualFree(callbackInstance1, 0, MEM_RELEASE); VirtualFree(callbackInstance2, 0, MEM_RELEASE); return 0; } ``` 在这个示例中,我们定义了一个包含静态回调函数 `StaticCallback` 和成员变量 `memberVariable` 的 `CallbackClass` 类。静态回调函数通过获取类的实例指针来访问成员变量。 我们使用 `GetCallbackInstance` 函数通过 `VirtualAlloc` 分配一块可执行的内存,并将类的实例指针存储在其中。 然后,我们创建了两个函数对象(lambda表达式),分别绑定到不同的静态回调函数。每个函数对象都对应一个独立的内存块,其中存储了不同的类实例。 最后,我们调用这两个函数对象,分别执行不同的静态回调函数,并访问对应类的成员变量。 请注意,这个示例代码使用了lambda表达式和std::function,使得函数对象能够绑定到静态回调函数,并在调用时访问类的成员变量。在实际应用中,您可能需要考虑更多的安全性和错误处理机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值