【问题标题】:Creation of controlled type will call finalize on return创建受控类型将在返回时调用 finalize
【发布时间】:2017-10-19 23:29:13
【问题描述】:

我想通过以下方式创建一个用于创建和初始化受控类型(有点像工厂)的函数:

function Create return Controlled_Type
is
  Foo : Controlled_Type;
begin
   Put_Line ("Check 1")
   return Foo;
end Create;

procedure Main
is
  Bar : Controlled_Type := Create;
begin
  Put_Line ("Check 2")
end Main;

output:
Initialize
Check 1
Adjust
Finalize

由于 finalize 将处理一些在受控类型中指向的对象,我最终会在 Bar 中出现悬空指针,并且不知何故这会立即使程序崩溃,所以我永远不会看到“检查 2”。

这可以通过使用新的 Controlled_Type 并在 Create 函数中返回一个指针来轻松解决。但是,我喜欢拥有受控类型而不是指向它的指针的想法,因为当 Bar 超出范围时将自动调用终结。如果 Bar 是一个指针,我必须手动处理它。

有什么方法可以正确地做到这一点而不会出现悬空指针?我应该在 Adjust 过程中施展魔法吗?

【问题讨论】:

    标签: factory ada dangling-pointer finalization


    【解决方案1】:

    嗯,你应该实现Adjust适当

    当你创建一个副本时,它是按位的,因此原始文件中的任何指针都会按原样复制到副本中。当原始对象完成并释放指向的对象时,副本中会留下一个指向超空间的指针。

    要做的是分配一个新指针,指定与原始指针相同的值。类似的东西

    with Ada.Finalization;
    with Ada.Text_IO; use Ada.Text_IO;
    with Ada.Unchecked_Deallocation;
    
    procedure Finalart is
    
       type Integer_P is access Integer;
       type Controlled_Type is new Ada.Finalization.Controlled with record
          P : Integer_P;
       end record;
       procedure Initialize (This : in out Controlled_Type);
       procedure Adjust (This : in out Controlled_Type);
       procedure Finalize (This : in out Controlled_Type);
    
       procedure Initialize (This : in out Controlled_Type) is
       begin
          Put_Line ("initialize");
          This.P := new Integer'(42);
       end Initialize;
    
       procedure Adjust (This : in out Controlled_Type) is
          Original_Value : constant Integer := This.P.all;
       begin
          Put_Line ("adjust");
          This.P := new Integer'(Original_Value);
       end Adjust;
    
       procedure Finalize (This : in out Controlled_Type) is
          procedure Free is new Ada.Unchecked_Deallocation (Integer, Integer_P);
       begin
          Put_Line ("finalize");
          Free (This.P);
       end Finalize;
    
       function Create return Controlled_Type is
          CT : Controlled_Type;
       begin
          Put_Line ("check 1");
          return CT;
       end Create;
    
       Bar : Controlled_Type := Create;
    begin
       Put_Line ("check 2");
    end Finalart;
    

    如果我在 Adjust 中注释掉 This.P := new Integer'(Original_Value); 行,我会得到(在 macOS 上)

    $ ./finalart 
    initialize
    check 1
    adjust
    finalize
    adjust
    finalize
    finalart(35828,0x7fffd0f8b3c0) malloc: *** error for object 0x7fca61500000: pointer being freed was not allocated
    *** set a breakpoint in malloc_error_break to debug
    
    raised PROGRAM_ERROR : unhandled signal
    

    【讨论】:

    • 非常感谢您的广泛回答,它确实帮助我了解了如何实施 Adjust 程序。在我的具体情况下,我在主要受控类型下有一个树数据结构,需要一些递归调整过程,但最终它就像一个魅力。
    猜你喜欢
    • 2018-12-18
    • 2011-08-17
    • 1970-01-01
    • 2011-10-22
    • 2021-11-21
    • 1970-01-01
    • 2011-06-16
    • 2018-01-06
    • 2011-03-09
    相关资源
    最近更新 更多