C++/CLI 资源管理混乱
我对 C++/CLI 中的资源管理非常困惑。我以为我有一个句柄(没有双关语),但我在查看头文件时偶然发现了 auto_gcroot
类,这导致了谷歌搜索,然后是一天中的大部分时间阅读文档,现在很困惑。所以我想我应该求助于社区。
我的问题涉及 auto_handle/stack 语义和 auto_gcroot/gcroot 之间的区别。
auto_handle:我的理解是,这将清理在托管函数中创建的托管对象。我的困惑是垃圾收集器不应该为我们做这件事吗?这不是托管代码的全部意义吗?更具体地说:
现在,如果它是 C# using 关键字的替代品,这对我来说是有意义的,并且仅建议与 Bitmap 等资源密集型类型一起使用,但文档中没有提到这一点,所以我担心我已经泄漏了现在一直内存//后面的都是托管代码 无效WillThisLeak(无效) { 字符串 ^str = gcnew 字符串 ^(); //我刚刚泄漏了内存吗?或者GC会清理这个吗?如果抛出异常怎么办? } 无效NotGoingToLeak(无效) { 字符串 ^str = gcnew 字符串 ^(); 删除str; //保证不泄露,但是有这个必要吗? } 无效也不会泄漏(无效) { auto_handle
; str = gcnew String^(); //也保证不泄露,但是有这个必要吗? } void DidtEvenKnowICouldDoThisUntilToday(void) { 字符串 str(); //也保证不泄露,但是有这个必要吗? } auto_gcroot
我可以将它作为参数传递给本机函数吗?副本上会发生什么?
void function(void)
{
auto_gcroot<Bitmap ^> bmp = //load bitmap from somewhere
manipulateBmp(bmp);
pictureBox.Image = bmp; //Is my Bitmap now disposed of by auto_gcroot?
}
#pragma unmanaged
void maipulateBmp(auto_gcroot<Bitmap ^> bmp)
{
//Do stuff to bmp
//destructor for bmp is now called right? does this call dispose?
}
如果我使用 gcroot 来代替,这会起作用吗?
此外,拥有 auto_handle 和 auto_gcroot 有什么好处?看起来他们做的事情很相似。
我一定是误解了一些东西,所以这毫无意义,所以一个好的解释会很好。此外,有关正确使用这些类型的任何指导、我可以去学习这些东西的地方以及我可以找到它们的任何更多良好实践/地方将不胜感激。
多谢, 最大限度
I am extremely confused about resource management in C++/CLI. I thought I had a handle (no pun intended) on it, but I stumbled across the auto_gcroot<T>
class while looking through header files, which led to a google search, then the better part of day reading documentation, and now confusion. So I figured I'd turn to the community.
My questions concern the difference between auto_handle/stack semantics, and auto_gcroot/gcroot.
auto_handle: My understanding is that this will clean up a managed object created in a managed function. My confusion is that isn't the garbage collector supposed to do that for us? Wasn't that the whole point of managed code? To be more specific:
//Everything that follows is managed code void WillThisLeak(void) { String ^str = gcnew String ^(); //Did I just leak memory? Or will GC clean this up? what if an exception is thrown? } void NotGoingToLeak(void) { String ^str = gcnew String^(); delete str; //Guaranteed not to leak, but is this necessary? } void AlsoNotGoingToLeak(void) { auto_handle<String ^> str = gcnew String^(); //Also Guaranteed not to leak, but is this necessary? } void DidntEvenKnowICouldDoThisUntilToday(void) { String str(); //Also Guaranteed not to leak, but is this necessary? }
Now this would make sense to me if it was a replacement for the C# using keyword, and it was only recommended for use with resource-intensive types like Bitmap, but this isnt mentioned anywhere in the docs so im afraid ive been leaking memory this whole time now
auto_gcroot
Can I pass it as an argument to a native function? What will happen on copy?
void function(void)
{
auto_gcroot<Bitmap ^> bmp = //load bitmap from somewhere
manipulateBmp(bmp);
pictureBox.Image = bmp; //Is my Bitmap now disposed of by auto_gcroot?
}
#pragma unmanaged
void maipulateBmp(auto_gcroot<Bitmap ^> bmp)
{
//Do stuff to bmp
//destructor for bmp is now called right? does this call dispose?
}
Would this have worked if I'd used a gcroot instead?
Furthermore, what is the advantage to having auto_handle and auto_gcroot? It seems like they do similar things.
I must be misunderstanding something for this to make so little sense, so a good explanation would be great. Also any guidance regarding the proper use of these types, places where I can go to learn this stuff, and any more good practices/places I can find them would be greatly appreciated.
thanks a lot,
Max
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请记住,在托管对象上调用的
delete
类似于在 C# 中调用 Dispose。所以你是对的,auto_handle 可以让你执行 C# 中using
语句的操作。它确保在作用域结束时调用delete
。所以,不,如果您不使用 auto_handle (垃圾收集器负责处理),您就不会泄漏托管内存,您只是无法调用 Dispose。如果您处理的类型没有实现 IDisposable,则无需使用 auto_handle。当您想要保留本机类中的托管类型时,请使用 gcroot。您不能直接使用帽子
^
符号在本机类型中声明托管类型。您必须使用 gcroot。这是一个“垃圾收集根”。因此,当 gcroot(本机对象)存在时,垃圾收集器无法收集该对象。当 gcroot 被销毁时,它会释放该引用,并且垃圾收集器可以自由地收集该对象(假设它没有其他引用)。您可以像上面那样在方法中声明一个独立的 gcroot - 只需尽可能使用 hat^
语法即可。那么什么时候会使用auto_gcroot呢?当您需要保留本机类中的托管类型并且该托管类型恰好实现 IDisposable 时,将使用它。在销毁 auto_gcroot 时,它将执行两件事:对托管类型调用删除(将其视为 Dispose 调用 - 不会释放内存)并释放引用(以便可以对类型进行垃圾收集)。
希望有帮助!
一些参考:
http://msdn.microsoft.com /en-us/library/aa730837(v=vs.80).aspx
http://msdn.microsoft.com/en-us/库/481fa11f(v=vs.80).aspx
http://www.codeproject.com/Articles/14520 /C-CLI-互操作场景库类
Remember
delete
called on managed object is akin to calling Dispose in C#. So you are right, that auto_handle lets you do what you would do with theusing
statement in C#. It ensures thatdelete
gets called at the end of the scope. So, no, you're not leaking managed memory if you don't use auto_handle (the garbage collector takes care of that), you are just failing to call Dispose. there is no need for using auto_handle if the types your dealing with do not implement IDisposable.gcroot is used when you want to hold on to a managed type inside a native class. You can't just declare a manged type directly in a native type using the hat
^
symbol. You must use a gcroot. This is a "garbage collected root". So, while the gcroot (a native object) lives, the garbage collector cannot collect this object. When the gcroot is destroyed, it lets go of the reference, and the garbage collector is free to collect the object (assuming it has no other references). You declare a free-standing gcroot in a method like you've done above--just use the hat^
syntax whenever you can.So when would you use auto_gcroot? It would be used when you need to hold on to a manged type inside a native class AND that managed type happens to implement IDisposable. On destruction of the auto_gcroot, it will do 2 things: call delete on the managed type (think of this as a Dispose call--no memory is freed) and free the reference (so the type can be garbage collected).
Hope it helps!
Some references:
http://msdn.microsoft.com/en-us/library/aa730837(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/481fa11f(v=vs.80).aspx
http://www.codeproject.com/Articles/14520/C-CLI-Library-classes-for-interop-scenarios