Ада проблема с STORAGE_ERROR
У меня есть эта небольшая функция, которая вызывает у меня головные боли на RHEL6, и я не уверен, что происходит... и это отладка. Когда я запускаю это, я получаю STORAGE_ERROR, поэтому я сделал gstack, чтобы увидеть, где висит программа (см. Ниже). Это похоже на проблему с memcmp, хотя я не уверен, где / как он вызывается.. Есть идеи для обхода?
Когда я изменяю эту функцию так, чтобы она просто возвращала true, она, кажется, работает нормально (STORAGE_ERROR исчезает), поэтому я полагаю, что проблема заключается в некоторой логике в этой части: (Ada.Characters.Handling.To_Upper (EPS_List (1). все) = "ЛОКАЛЬНОСТЬ");
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 ответа
Мое абсолютное первое предположение здесь будет 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;
...
Что касается вашего редактирования, мое лучшее предположение о том, почему перемещение объявления предотвращает сбой, заключается в том, что это меняется, когда происходит эта инициализация. Сейчас это происходит намного раньше. Опять же, может быть полезно вернуть его в состояние сбоя и попытаться выяснить с помощью отладчика и / или отладочных операторов печати, что именно происходит.