Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.12.30;
Скачать: CL | DM;

Вниз

EStackOverflow   Найти похожие ветки 

 
Дуся ©   (2002-10-23 13:35) [0]

Господа!.. Хочется рыдать уже, но все равно не поможет...

Программа вдруг ни с того ни с сего выдает EStackOverflow внутри процедуры, выполняющейся в отдельном thread. Ладно если бы просто вываливала exception, но затем она просто тихо закрывает приложение. Хотя блок try..except отрабатывает - в логе об этом есть запись.
Процедура самая обычная, обходит список и что-то с каждым элементом делает или не делает в зависимости от статуса. Длина списка порядка 300 элементов. Вызывается за день кучу раз - примерно каждые 2 секунды.
Такой ошибки не встречала раньше никогда.
Вопроса два: с чего бы это, и можно ли как-то это так отлавливать
чтобы она все не роняла!..
Помогите!..
Приложение онлайновое, жутко важное, топор близится.. :(


 
Opuhshii ©   (2002-10-23 13:53) [1]

Рекурсия у Вас,
"просто тихо закрывает приложение" - правильно,. почитайте Рихтера поймете почему,.. это очень правильно... ;)


 
Дуся ©   (2002-10-23 13:57) [2]

Рекурсии йок.
В хелпе написано "либо рекурсия, либо очень большие локальные переменные" (extremely large local variables) - это как так - очень большие?!..
и почему валится-то не на каждом проходе, а от балды ?..



 
Игорь Шевченко ©   (2002-10-23 14:04) [3]

Код в студию. Телепатов здесь нету


 
Дуся ©   (2002-10-23 14:12) [4]

procedure TInstrOperator.CheckDataBase;
Var
i : integer;
LCount : integer;
begin
try
if InsideList = nil then exit;
LCount := InsideList.Count - 1;
StatusForm.FIProgress.Max:=LCount+1;
StatusForm.AllFI.caption:= IntToStr(LCount+1);

if NoNewFI and NoNewQueue then
exit;

WriteToLogFile("TInstrOperator.CheckDataBase. Lcount = "+IntToStr(LCount));
for i := 0 to LCount do
begin
WorkInstr := InsideList.Items[i];
if WorkInstr <> nil then
begin
if (WorkInstr.Board < 0){ or (WorkInstr.Board > 4) }then
begin
if WorkInstr.Board <> 11 then continue;
end;

if WriteInitToBase then
if not WorkInstr.InitOnDataBase then WorkInstr.InitDataBase;

if WorkInstr.InitOnDataBase then
if not WorkInstr.OnDataBase then WorkInstr.ToDataBase;

WorkInstr.SequenceToDataBase;
StatusForm.FIProgress.Position := i;
StatusForm.I1.Caption := IntToStr (i+1);
end;
end;
StatusForm.FIProgress.Position := StatusForm.FIProgress.Max;
StatusForm.FIProgress.Position := 0;
StatusForm.i1.Caption := "";

except
on E:Exception do
WriteToLogFile("TInstrOperator.CheckDataBase " + E.ClassName+":"+E.Message);
end;

end;


 
Дуся ©   (2002-10-23 14:14) [5]

Вот... Если кому понятно что-то вообще...


 
Opuhshii ©   (2002-10-23 14:19) [6]

лажа скорее всего не здесь,...


 
Дуся ©   (2002-10-23 14:25) [7]

а где?..
Внутри одного из вызываемых методов?..
но тогда там бы и валилось - там тоже проверок наставлено сверх меры...


 
Opuhshii ©   (2002-10-23 14:32) [8]

Скорее всего внутри одного из вызываемых методов скорее всего вызывается TInstrOperator.CheckDataBase; ,..


 
Дуся ©   (2002-10-23 14:35) [9]

Нет, не вызывается.
Рекурсии нет.


 
Opuhshii ©   (2002-10-23 14:42) [10]

я склонен полагать что рекурсия есть, хотя возможно(навряд ли) передача переменных(очень больших) через стек,... вороться указанием var const в параметрах......


 
Дуся ©   (2002-10-23 14:46) [11]

Какие параметры?!... Это все методы класса!..

Может это что-то на уровне железа?


 
Opuhshii ©   (2002-10-23 14:48) [12]

2Дуся © (23.10.02 14:46)
у метода класса не может быть параметров передаваемых через стек?
"Может это что-то на уровне железа?" - неверю!


 
Дуся ©   (2002-10-23 14:58) [13]

Где вы в запостеном коде видели параметры?..
Нету их, чесслово.

А вот с железом предположение имеет вероятность отличную от нуля...


 
Digitman ©   (2002-10-23 16:44) [14]


> А вот с железом предположение имеет вероятность отличную
> от нуля...


Ерунда полная.

Ты вообще трассировать пыталась сей код ?


 
Дуся ©   (2002-10-23 16:55) [15]

А то.
Только я же говорю - валится иногда, раз в сутки, безсистемно. У меня такого смоделировать не получилось ни разу.
Как такое может быть?..


 
Digitman ©   (2002-10-23 17:02) [16]

приведи код Execute()


 
Дуся ©   (2002-10-23 17:13) [17]

Да там вообще очень глубоко копать....
Вызывается в цикле некий метод, в котором в результате вызывается этот метод этого объекта. Кроме него еще до фига всего прочего... Однако. После падения последняя запись в логе -
TInstrOperator.CheckDataBase EStackOverflow:Stack overflow
К сожалению, подробное логирование включила только вчера, с тех пор упало всего раз. Может в другой раз упадет в другой процедуре - и тогда мои подозрения насчет железа станут осязаемее.. Или нет?


 
Digitman ©   (2002-10-23 17:46) [18]


> мои подозрения насчет железа станут осязаемее


даже не думай.
никакого железа.
только - программа виновата.

попробуй включить в лог инф-цию о состоянии стека ИМЕННО на момент входа в каждую из подозрительных процедур/ф-ций, т.е. в тех точках, где вероятность локального исключения практически отсутствует

момент начала в логе подозрительно стабильного уменьшения значения указателя стека (в совокупности с инф-цией о текущих в этот момент процедурах/ф-циях) вполне может дать уже что-то конкретное

фиксируй ид-р тек.код.потока процесса для сопоставления со стеком, ибо каждый код.поток процесса имеет свой собственный стек

состояние указателя стека и ID тек.код.потока читай так :

var
sp: DWord; // лок.переменная для фиксации указателя стека для тек.метода
tid: DWord; // лок.переменная для фиксации id код.потока, в котором выполняется тек.метод
...
begin
tid := GetCurrentThreadId; //
asm
mov [sp], esp
end;
// здесь - запись в лог значений sp и tid
...

end;




 
Игорь Шевченко ©   (2002-10-23 18:03) [19]

В JCL (www.delphi-jedi.org) есть трассировщик стека. Unit JCLDebug.pas


 
Дуся ©   (2002-10-24 09:34) [20]

Блин... Со стеком напрямую я-то никогда не работала.. На что там обращать внимание?..


 
Digitman ©   (2002-10-24 09:59) [21]

попросту (без лишних премудростей) :

стек - структура памяти типа LIFO, автоматически "ведомая" процессором

фигурирует понятие "указатель на вершину стека" :

- "растет" стек - уменьшается указатель
- "уменьшается" стек - увеличивается указатель

при вызове п/программы стек "растет" на величину, равную размеру ссылки на адрес возврата + полный размер параметров (если имеются) + (иногда) размер результата

при возврате из п/программы стек "уменьшается" на ту же величину, на какую он "вырос" в ходе вызова п/программы

в теле п/программы стек тоже может "дышать", но к моменту возврата из тела, как правило, д.б. таким же как и в момент входа в тело

тем самым достигается т.н. "баланс" стека

переполнение стека есть нарушение его баланса, в рез-те которого стек "вырос" до крит.размера

если п/программа бесконечно вызывает саму себя (см.все о бесконечной рекурсии), возникает как раз ситуация с переполнением стека, ибо стек - не "резиновый" и имеет строго определенный размер

о размере стека можно судить по указателю на его вершину

как прочитать состояние указателя вершины стека - пример приведен


 
Дуся ©   (2002-10-24 17:15) [22]

Теперь с ассемблером проблемы :(
Забыла напрочь.

А компилятор ругается на mov [sp], esp : Invalid register combination.


 
Anatoly Podgoretsky ©   (2002-10-24 17:20) [23]

Привелигированный регистр, только в кольце 0
Кроме того sp это 16 битный, а esp 32 битный, что и является недопустимой комбинацией.


 
Дуся ©   (2002-10-24 17:28) [24]

Как я поняла, тут надо куда-нибудь сунуть значение из регистра esp. Осталось понять, как в код ассемблера вставить адрес переменной ...


 
Digitman ©   (2002-10-24 17:36) [25]

ох, ну я ж - к примеру) неудачный пример с именем переменной оказался ... ид-р "SP" в контексте asm-блока компилятор считает зарезервированным именем регистра, отсюда и проблема)...

ну обзови ты ее хоть StackPointer :

var
StackPointer: DWord;

..
mov [StackPointer], esp


 
Дуся ©   (2002-10-24 17:42) [26]

Все. Понятно. Квадратные скобочки ни к чему.
ЗАРАБОТАЛО!..

Все, наставила диагностики, будем ждать облома.


 
VMcL   (2002-10-25 20:13) [27]

Возможно поможет следующий приём:

<pre>
procedure TInstrOperator.CheckDataBase;
const
Already: Boolean = False;
// ...
begin
if Already then Exit;

Already := True;
try
// Собственно тело процедуры
finally
Already := False;
end;
end;
</pre>



Страницы: 1 вся ветка

Текущий архив: 2002.12.30;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.017 c
3-98972
Kirill S.
2002-12-10 09:33
2002.12.30
сортировка DataSet


6-99228
xnick
2002-11-04 09:52
2002.12.30
Pipe


3-98967
epifansan
2002-12-10 08:45
2002.12.30
Подскажите как обойтись без регистрации своих баз в БД


14-99355
Skurihin Aleksey
2002-12-10 19:30
2002.12.30
никому нетребуеться подающий большие потребности программист?


3-98986
Kolyan
2002-12-10 13:40
2002.12.30
Загнал базу dBase III+ на SQL Server 7.0. Memo не работает!