Ада проблема с STORAGE_ERROR - PullRequest
1 голос
/ 08 июля 2011

У меня есть эта небольшая функция, которая вызывает у меня головную боль на RHEL6, и я не уверен, что происходит ... и отладка - это боль.Когда я запускаю это, я получаю STORAGE_ERROR, поэтому я сделал gstack, чтобы увидеть, где висит программа (см. Ниже).Это похоже на проблему с memcmp, хотя я не уверен, где / как он вызывается. Есть идеи для обхода?

Когда я изменяю эту функцию, чтобы просто вернуть 'true', она, кажется, работает нормально(STORAGE_ERROR исчезает), поэтому я считаю, что проблема заключается в некоторой логике в этой части: (Ada.Characters.Handling.To_Upper (EPS_List (1) .all) = "LOCALHOST");

  function Localhost_Only return Boolean is
  --++
     EPS_List : String_List_Type 
              := Values(Bstring.To_Bounded_String("EPS"));
  begin
    return (Ada.Characters.Handling.To_Upper(EPS_List(1).all) = "LOCALHOST");

  end Localhost_Only;

НАЧАТЬ РЕДАКТИРОВАТЬ ***

Еще один способ, которым workst делал это (Выносил его из области действия функции ... Почему это работает?):

   EPS_List : String_List_Type 
              := Values(Bstring.To_Bounded_String("EPS"));

  function Localhost_Only return Boolean is
  --++

  begin
    return (Ada.Characters.Handling.To_Upper(EPS_List(1).all) = "LOCALHOST");

  end Localhost_Only;

КОНЕЦ РЕДАКТИРОВАНИЯ ***

gstack вывод на процесс:

Thread 1 (Thread 0x407059a0 (LWP 13610)):
#0  0x40000424 in __kernel_vsyscall ()
#1  0x00b2b2fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0
#2  0x0b53dd9e in system__tasking__stages__vulnerable_complete_master ()
#3  0x0b53e242 in system__tasking__stages__finalize_global_tasks ()
#4  0x0b5845d3 in __gnat_last_chance_handler ()
#5  0x0b545c50 in ada__exceptions__exception_traces__unhandled_exception_terminateXn ()
#6  0x0b5459de in ada__exceptions__exception_propagation__propagate_exceptionXn ()
#7  0x0b5465c5 in __gnat_raise_nodefer_with_msg ()
#8  0x0b5469ed in ada__exceptions__raise_with_location_and_msg ()
#9  0x0b5469b8 in __gnat_raise_storage_error_msg ()
#10 0x0b546f98 in __gnat_rcheck_31 ()
#11 0x0b5363de in system__interrupt_management__notify_exception ()
#12 <signal handler called>
#13 0x0bcef590 in memcmp@@GLIBC_2.0 ()
#14 0x084a83c9 in common_network_configuration__localhost_only ()

Соответствующие типы/ функция:

type Number_Of_Items_Type is range 0 .. 250;

subtype Index_Type is Number_Of_Items_Type 
     range Number_Of_Items_Type'First + 1 .. Number_Of_Items_Type'Last;

type String_List_Type is array (Index_Type range <>) 
     of String_Access.String_P_Type;

package Bstring is new Ada.Strings.Bounded.Generic_Bounded_Length 
                            (Max => Line_Length_Type'last);

   function Values(Name : Bstring.Bounded_String) return String_List_Type is
   --++
   -- ABSTRACT
   --   Return a list of pointers to strings. The strings are all the values
   --   associated with the specified name. All values are recursively 
   --   evaluated so that each entry in the returned list is a primitive
   --   name (i.e. integer, ip_address, or unix_workstation).
   --
   --   If a circular definition is detected, an empty list is returned. 
   --
   -- LOCAL DATA
     -- Number of items in list
     Count    : Number_Of_Items_Type := 0;

     -- List of pointers to strings containing the primitive values
     Out_List : String_List_Type (1 .. Index_Type'Last);

     -- The Index of the item being evaluated
     Item     : Config_Index_Type := 0;

     -- A safety net, to detect and prevent unlimited recursion, such as 
     -- will happen in the case of a circular definition.
     Depth    : Number_Of_Items_Type := 0;

     procedure Find_Values (Name : in Bstring.Bounded_String) is
     --++ 
     -- ABSTRACT
     --   This procedure recursively calls itself until it makes it all 
     --   The way through the Config_Array without finding a match on the
     --   specified Name. The index of the last name for which a match was
     --   found is used to get the value associated with that Name. This 
     --   is a primitive value associated with the name and is added to the
     --   Out_List. 
     --
     --   Depth is used to count the recursion depth, when it reaches a 
     --   maximum, no more recursive calls are made, preventing an endless
     --   loop in the case of a direct or indirect circular definition.
     begin 
       Depth := Depth + 1;
       for Index in 1 .. Config_Count loop
         if  Name_Match(Bstring.To_String(Name),Index) 
         and Count < Number_Of_Items_Type'last 
         and Depth < Number_Of_Items_Type'last then
           Item := Index;
           Find_Values (Config_Array(Index).Value);
         end if;
       end loop;
       if Item /= 0 then
         if Count < Number_Of_Items_Type'last then
           Count := Count + 1;
           Out_List(Count) := Config_Array(Item).Val_Ptr;
         end if;
         Item := 0;
       end if;
     end Find_Values;

   begin -- Values
     Find_Values(Name);
     if Depth < Number_Of_Items_Type'last then
       return Out_List(1..Count);
     else 
       return Null_String_List;
     end if;
   end Values;

Ответы [ 2 ]

2 голосов
/ 08 июля 2011

Мое абсолютное первое предположение здесь было бы, что EPS_List(1) не указывает на допустимое место в памяти. Вы это проверяли?

Насколько я могу судить, этот массив в конечном итоге загружается из указателей из чего-то с именем Config_Array. Так что, если это не инициализируется, когда происходит загрузка, или если память, на которую ссылаются эти указатели, освобождается до вызова Localhost_Only, у вас будут ошибки такого рода.

Этот код достаточно сложен, чтобы я мог зайти в Localhost_Only и проверить это. Либо используйте отладчик для просмотра этих указателей, либо добавьте код отладки перед оператором return, чтобы отобразить их значения.

Кроме того, ваша подпрограмма Localhost_Only принимает массив без ограничений, а затем предполагает, что он содержит элемент 1. Если этого не произойдет, я полагаю, что вы должны получить что-то вроде Constraint_Error или Range_Error, но если вы отключите проверку диапазона вашего компилятора, вместо этого может получиться Storage_Error. В любом случае, вы должны как-то защититься от этой возможности. Что-то вроде if EPS_List'length > 0 then return False; end if; ...


Что касается вашего редактирования, моя лучшая догадка о том, почему перемещение объявления предотвращает сбой, заключается в том, что это изменится , когда произойдет инициализация. Сейчас это происходит намного раньше. Опять же, может оказаться полезным вернуть его в состояние сбоя и попытаться выяснить с помощью отладчика и / или отладочных операторов печати, что именно происходит.

1 голос
/ 18 июля 2011

Решением было обновить компилятор на RHEL6 ..

...