Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Terminal 将日志放在无限循环生成的标准输出上的最佳方式是什么?_Terminal_Memory Leaks_Infinite Loop_Ada - Fatal编程技术网

Terminal 将日志放在无限循环生成的标准输出上的最佳方式是什么?

Terminal 将日志放在无限循环生成的标准输出上的最佳方式是什么?,terminal,memory-leaks,infinite-loop,ada,Terminal,Memory Leaks,Infinite Loop,Ada,我正在使用Adacore的PolyORB(DSA个性)开发一个(多)客户机-服务器环境 我有一个共享的被动分区,它基本上包含一个受保护的类型(数组),服务器每秒用来自客户端的信息不间断地更新它 我创建了一个带有无限循环的非常简单的主单元,用于监视该数组的内容 正如预期的那样,在标准输出上每秒打印一次数组行会消耗系统内存 如果可能的话,我希望避免在文件上打印信息,并运行tail-f命令。我不想乱搞磁盘,现在客户端的数量是有限的,但它预计会增长,性能可能会受到影响 另一方面,我尝试通过脚本杀死监视器

我正在使用Adacore的PolyORB(DSA个性)开发一个(多)客户机-服务器环境

我有一个共享的被动分区,它基本上包含一个受保护的类型(数组),服务器每秒用来自客户端的信息不间断地更新它

我创建了一个带有无限循环的非常简单的主单元,用于监视该数组的内容

正如预期的那样,在标准输出上每秒打印一次数组行会消耗系统内存

如果可能的话,我希望避免在文件上打印信息,并运行tail-f命令。我不想乱搞磁盘,现在客户端的数量是有限的,但它预计会增长,性能可能会受到影响

另一方面,我尝试通过脚本杀死监视器并再次启动它,但不知何故,它似乎只工作一次。我杀了它,然后再次启动(OK),然后再次杀了它,然后启动(不OK)

有没有一种好方法可以在不耗尽内存的情况下,使用无限循环打印出大量关于标准输出的信息

我已经检查过没有其他问题导致内存泄漏,如果终端上没有打印信息,则内存没有问题

这是监视器主机的代码

with Ada.Text_IO;
with Shared_Table;
with GNAT.OS_Lib;

procedure monitor is

 -- Variables to run linux command clear
 ARGUMENTS : GNAT.OS_Lib.Argument_List := (1 => new String'(""));
 RESULT : Boolean := False;

begin

   loop

         -- Clearing the terminal after writing the content of the table.

         GNAT.OS_Lib.Spawn (Program_Name => "/usr/bin/clear",
                            Args         => ARGUMENTS,
                            Success      => RESULT);

         -- Printing out the content of the table on the standard output.

         Shared_Table.Visualize_Table (Shared_Table.Obtain_Table);

         delay 1.0;

   end loop;  

end monitor;

谢谢

这里是打印出可能导致内存泄漏的数组行的程序代码

procedure Visualize_Table (Shared_Table : in Shared_Table_Type) is
      
      -- Very big varibale containing adaptation data in a simple linked list.
      Adaptation_Data : Adaptation.Track_List.List;
      
      -- Segment type is a record. One of the components being a simple linked list of items.
      Segment_Aux : Segment.Segment_Type;

      -- Track Type is a record. One of the components being a simple linked list of segments.
      Track_Aux : Track.Track_Type;
      
      Number_of_items : Natural range 1 .. 3 := 1;
   
   begin
      
      -- Load adaptation data.
      Adaptation.Generate_Track_List (Adaptation_Data);
      
      -- Visualize header.
      Ada.Text_Io.Put_Line (" +-----------+---------------------------------+---------+---------------------------------+-------------+");
      Ada.Text_Io.Put_Line (" | xxxxxxxxx |          xxxxxxxxxxxx           | # Items |          xxxxxxxxxxxxxxx        |  xxxxxxxxx  |");
      Ada.Text_Io.Put_Line (" +-----------+---------------------------------+---------+---------------------------------+-------------+");
      
      for I in 1 .. Number_of_clients loop
            
         -- Visualize first two columns.
         Ada.Text_Io.Put (" | " & Shared_Table(I).First_Row & "  | ");
         Ada.Text_Io.Put (Shared_Table(I).Second_Row & "| ");
            
         -- Initialize auxiliar variables..
         Track.Initialize_Track (Track_Aux);
         Segment.Initizalize (Segment_Aux);

         Track.Set_Id (Id    => Shared_Table(I).Track_Id,
                       Track => Track_Aux);
         
         Segment.Set_Position (Position => Shared_Table(I).Position,
                               Segment  => Segment_Aux);
            
         Number_of_items := 
           Segment.List_of_items.Obtain_Number 
             (Segment.Obtain_List_of_items 
                (Track.List_of_segments.Find_Element 
                   (Element => Segment_Aux,
                    List    => Track.Obtain_Segment_List (Adaptation.Track_List.Find_Element (Element => Track_Aux,
                                                                                              List    => Adaptation_Data)))));
            
         Ada.Text_Io.Put (" |");

         Ada.Text_Io.Put ("    X : ");
         Ada.Integer_Text_Io.Put (Item => Shared_Table(I).Position_X,
                                  Width => 7);
         Ada.Text_Io.Put ("  Y : ");
         Ada.Integer_Text_Io.Put (Item => Shared_Table(I).Position_Y,
                                  Width => 7);
         Ada.Text_Io.Put ("     |");

         Ada.Integer_Text_Io.Put (Item => Shared_Table(I).Last_Row,
                                  Width => 3);
         Ada.Text_Io.Put_Line ("          |");
            
         Ada.Text_Io.Put_Line 
           (" +-----------+---------------------------------+---------+---------------------------------+-------------+");
         
      end loop;
      
   end Visualize_Table;
我的理解是,当过程完成打印出数组的行时,变量的生命应该结束,它们使用的内存应该是空闲的,但是如果某些变量是链表(使用访问类型),那么情况可能不是这样,这是可能的吗

这是usgin valgrind获得的日志的一部分

==17190== 61,799,120 (7,774,208 direct, 54,024,912 indirect) bytes in 60,736 blocks are definitely lost in loss record 816 of 816
==17190==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17190==    by 0x68D12E: __gnat_malloc (in /home/hector/ITS/distributed/src/monitor)
==17190==    by 0x691C7C: system__pool_global__allocate (in /home/hector/ITS/distributed/src/monitor)
==17190==    by 0x4CFD16: adaptation__track_list__insert_element (in /home/hector/ITS/distributed/src/monitor)
==17190==    by 0x4D6028: adaptation__generate_track_list (in /home/hector/ITS/distributed/src/monitor)
==17190==    by 0x4D991C: shared_table__visualize_table (in /home/hector/ITS/distributed/src/monitor)
==17190==    by 0x4DB9FE: _ada_monitor (in /home/hector/ITS/distributed/src/monitor)
==17190==    by 0x47926F: partition___elabb (in /home/hector/ITS/distributed/src/monitor)
==17190==    by 0x47BA56: adainit (in /home/hector/ITS/distributed/src/monitor)
==17190==    by 0x47BAC1: main (in /home/hector/ITS/distributed/src/monitor)
我可以看到其他一些内存泄漏,所有这些最终都指向在简单链表中插入新元素的过程的实例化

这是通用包的代码

   procedure Insert_Element (Element : in Type_Element;
                             List : in out Type_List) is
    
      Pointer_to_Cell : Type_Pointer_to_Cell := new Type_Cell'(Record_Element => Element,
                                                               Record_Pointer => List.Record_Initial_Cell);
      
   begin
      
      if List.Record_Number_of_elements <= Max_Number_of_elements then
         
         List.Record_Initial_Cell := Pointer_to_Cell;
         List.Record_Number_of_elements := List.Record_Number_of_elements + 1;
         
      else
         
         raise List_Full_Exception;
         
      end if;

   end Insert_Element;
过程插入元素(元素:在类型元素中;
列表:输入输出类型(列表)为
指针指向单元格:类型指针指向单元格:=新类型单元格'(记录元素=>元素,
记录\u指针=>List.Record\u初始单元格);
开始

如果元素的List.Record\u Number\u使用循环缓冲区的一般受保护对象可以如下所示:

-----------------------------------------------------------------------
-- Generic Bounded Protected Queue
-----------------------------------------------------------------------

generic
   type Element_Type is private;
   type Queue_Index is mod <>;
package Generic_Protected_Bounded_Queue is
   type Buffer is array (Queue_Index) of Element_Type;

   protected type Queue is
      function Capacity return Natural;
      function Is_Full return Boolean;
      function Is_Empty return Boolean;
      entry Enqueue (Value : in Element_Type);
      entry Dequeue (Value : out Element_Type);
      procedure Clear;
   private
      Buf   : Buffer;
      Head  : Queue_Index := 0;
      Tail  : Queue_Index := 0;
      Count : Natural     := 0;
   end Queue;

end Generic_Protected_Bounded_Queue;
当然,由于外部循环,任务会占用大量CPU资源。该循环执行轮询操作,而不是等待数据可用。共享表应实现为一个有界缓冲区。当缓冲区为空时,读取任务将挂起,并且仅当数据可用时才读取数据

请参见以下使用有界队列包的示例:

with Ada.Text_IO; use Ada.Text_IO;
with generic_protected_bounded_queue;

procedure Main is
   type Index_T is mod 10;
   package int_queue is new generic_protected_bounded_queue(Element_Type => Integer,
                                                            Queue_Index  => Index_T);
   use int_queue;

   The_Queue : Queue;

   task producer;
   task body producer is
   begin
      Put_Line("Producer started.");
      for Num in 1..20 loop
         The_Queue.Enqueue(Num);
         Put_Line("Enqueued" & Num'Image);
      end loop;
      Put_Line("Producer terminating.");
   end Producer;

   task consumer;
   task body consumer is
      Num : Integer;
   begin
      Put_Line("Consumer started.");
      for Val in 11..30 loop
         The_Queue.Dequeue(Num);
         Put_Line("Dequeued" & Num'Image);
      end loop;
      Put_Line("Consumer terminating.");
   end Consumer;

begin
   null;
end Main;

不是PolyORB的专家,只是一些需要澄清的问题。现在还不完全清楚监视器程序在您第二次启动时是如何失败的。它是报告内存错误还是只是挂起?你看到内存消耗失控了吗?它是否真的重新加入/重新连接到(DSA)程序并接收新数据?在您终止监控程序后,DSA应用程序的其余部分是否仍能正常运行?您是否可以给出一些指示,说明每次循环迭代要向输出输出打印多少行/字符,以了解内存可能会成为问题的原因?第二次尝试重新启动监视器时,它看起来像是挂起了,标准输出上没有打印出任何内容。记忆绝对不是失控的。顺序如下,第一次运行(OK),第二次运行(OK)后续运行(not OK)。在我关闭监视器后,DSA应用程序的其余部分保持平稳运行。在每次迭代中,打印的文本不超过7行,每行不超过107个字符。如何同步对
Shared_Table
的访问?如果将对
Spawn
的调用更改为
Ada.text_IO.New_行(间距=>100),会发生什么情况
?@trashgod访问的对象数组是受Ada保护的类型。当我调用函数来获取数组时,我实际上使用了受保护对象本身的函数,这保证了在我访问数据时数据不会被写入。换句话说,没有同步,值得一试。至少它给了我一条新的探索之路。我会在这里张贴的结果,一旦我可以测试它。谢谢!我刚刚完成了这种方法的测试,我担心内存消耗要高得多(几乎高出3倍)。我应该指出,客户端每秒都会向服务器发送更新的信息。您能显示日志任务的代码吗?每秒一次非常慢。任务应该挂起,直到在缓冲区中读取数据。一旦数据准备好,任务应该读取数据,记录它,然后再次尝试读取缓冲区。在1秒的大部分时间内,日志记录任务应该挂起,不使用CPU。Shared_表是在Shared_被动包中定义的,只有无entryless保护类型才可用。我需要通过不同的分区以可靠的方式访问数据。设计共享_表的人做得很差。
task Visualize_Data;
   
   task body Visualize_Data is
      
      Arguments : GNAT.OS_Lib.Argument_List := (1 => new String'(""));
      Result  : Boolean := False;

   begin
      
      loop
         
         if Shared_Table.Obtain_Rows > 0 then
            
            Shared_Table.Visualize_Header;

            for I in 1 .. Shared_Table.Obtain_Rows loop
            
               declare
           
                  Row : Shared_Table.Row;
         
               begin
         
                  Bounded_Buffer.Queue.Dequeue (Row);
                  Shared_Table.Visualize_Row (Row);
                  
               end;

            end loop;
                  
            
            GNAT.OS_Lib.Spawn (Program_Name => "/usr/bin/clear",
                               Args                  => Argument,
                               Success             => Result);
            
         end if;
         
      end loop;
      
   end Visualize_Data;
with Ada.Text_IO; use Ada.Text_IO;
with generic_protected_bounded_queue;

procedure Main is
   type Index_T is mod 10;
   package int_queue is new generic_protected_bounded_queue(Element_Type => Integer,
                                                            Queue_Index  => Index_T);
   use int_queue;

   The_Queue : Queue;

   task producer;
   task body producer is
   begin
      Put_Line("Producer started.");
      for Num in 1..20 loop
         The_Queue.Enqueue(Num);
         Put_Line("Enqueued" & Num'Image);
      end loop;
      Put_Line("Producer terminating.");
   end Producer;

   task consumer;
   task body consumer is
      Num : Integer;
   begin
      Put_Line("Consumer started.");
      for Val in 11..30 loop
         The_Queue.Dequeue(Num);
         Put_Line("Dequeued" & Num'Image);
      end loop;
      Put_Line("Consumer terminating.");
   end Consumer;

begin
   null;
end Main;