科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Visual C++中删除托管对象、包装库及其他

Visual C++中删除托管对象、包装库及其他

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文将给大家讲解一下Visual C++中如何删除托管对象、包装库及其他,大家在实际开发中可以做个参考。

作者:Paul DiLascia 来源:msdn中国 2007年11月20日

关键字: Visual C++ 删除 托管对象 包装库

  • 评论
  • 分享微博
  • 分享邮件
本文将给大家讲解一下Visual C++中如何删除托管对象、包装库及其他,大家在实际开发中可以做个参考。

  问:能否告诉我,在托管 C++ 中,使用 delete 操作符销毁托管对象是否安全?

  Bernie Sanders

  答:是安全的,可以在托管 C++ 中删除托管对象,不过要知道,delete 所做的就是调用对象的析构函数,所以必须显式定义它。调用 delete 并没有释放对象的存储空间。只有垃圾回收器才能够释放存储空间。图 1 所示的是一个简单的程序,它定义了一个托管类,这个类有一个析构函数,当运行这个析构函数时会显示一条消息。TESTDTOR 分配了两个 ManagedClass 实例。它显式删除第一个实例,但没有删除第二个。当您运行 TESTDTOR 时,就会得到如下所示的结果:

以下是引用片段:
  Begin main
  ManagedClass(04A712D4)::ctor
  ManagedClass(04A712D4)::dtor
  ManagedClass(04A712E0)::ctor
  End main
  ManagedClass(04A712E0)::dtor

  它表明当 delete 语句执行时,第一个对象的析构函数就会立即执行,而第二个对象(位于 04A712E0)并没有被销毁,直到控制离开 main,系统终止代码调用垃圾回收器释放未完成对象时才被销毁。

testdtor 的重要部分

  图 2 testdtor 的重要部分

  要是对 .NET 环境中所发生的事情不确定,随时可以编写一些代码,对其进行编译,然后检查生成的 Microsoft 中间语言 (MSIL)。如图 2 所示,定义一个析构函数会使编译器生成两个方法:一个是 Finalize 方法,它包含您的实现(在本例中为调用 printf);另一个是 __dtor 方法,它调用 System.GC::SuppressFinalize,然后调用 Finalize。当您删除一个对象时,编译器会调用这个特定的 __dtor 方法。如果您带 /FAs 参数编译 TESTDTOR,产生随源代码列出的汇编语言,您就会发现 delete 语句按照以下方式进行编译:

以下是引用片段:
  delete pmc;
  ldloc.0 ; _pmc$
  call ..1ManagedClass@@$$FQ$AAM@XZ

  那些奇怪的神秘符号就是析构函数 (__dtor) 的托管名称。

  经验丰富的 C++ 编程人员也可能会疑惑不解,想知道如果调用 delete 不释放对象,那调用它有什么用呢?这个问题提得好。调用 delete 的唯一目的是回收类使用的任何非托管资源。例如,如果您的对象打开文件或创建一个数据库连接,则可以编写一个析构函数,当对象使用完毕时,可以用这个析构函数关闭它的资源,然后使用 delete 来调用它。释放托管类中的资源的更好方式是通过实现 Dispose 模式、IDisposable 和 auto_dispose 模式(如果您采用托管 C++ 编写)来调用它。有关更多信息,请参考 Tomas Restrepo 在 2002 年 2 月的 MSDN?Magazine 中撰写的“Tips and Tricks to Bolster Your Managed C++ Code in Visual Studio .NET”。

  如果您实现 dispose 模式,.NET 的其他用户就可以使用它。如果您在析构函数中进行清理工作,其他语言就无法显式调用您执行清理工作的代码。在 C# 和 Visual Basic 中没有 delete 操作符。

  所以虽然您可以调用 delete 来调用您的析构函数,但不提倡将执行清理工作的代码放在析构函数中。较好的方法是实现 IDisposable,所有的语言都可以使用它。不过要注意,这种行为在 Visual C++? 2005 中有所变化。有关更多信息,请参考 Andy Rich 在 Deterministic Finalization IV - Benefits, part II 中关于 deterministic finalization 的讨论,以及当前的 C++/CLI Language Specification Standard。

  问:我有一个非托管函数,它返回一个包含 char* 字符串的链接列表:

以下是引用片段:
  struct blah {
  int a, b;
  char *a, *b;
  struct blah *next;
  };
  struct blah *getmystruct();

  因为 getmystruct() 分配了内存,所以当我使用完这个函数后,我需要调用 freemystruct(struct blah *b)。我试图生成一个包装,将它转换成托管类型的集合,但我不知道当这些指针需要释放时如何处理它们。您能指点我一下吗?

  Cory Nelson

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章