Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 2002.12.30;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.015 c
14-99287
DiamondShark
2002-12-09 13:47
2002.12.30
Новый WEB-проект


14-99274
Anatoly Podgoretsky
2002-12-07 17:49
2002.12.30
Эстонская всреча Мастаков


6-99217
Sers
2002-11-02 10:56
2002.12.30
TWebBrowser.Document


14-99348
Malder
2002-12-11 00:02
2002.12.30
Цена на AMD 366


14-99329
KGB
2002-12-10 11:22
2002.12.30
Набор компонентов ABC





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский