|
Вопрос # 4 541/ вопрос открыт / |
|
Доброго времени суток, уважаемые эксперты!
Писал программку которая отображает битые ссылки в реестре.
Но через некоторое время работы программы возникает ошибка -переполнение стека.Долго искал в интернете - ничего.Тем более мне нужна привязка к коду.
Прилагаю скрин
К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)
Приложение: Переключить в обычный режим- procedure TRegistrySeach.Scan(Key: String);
- var
- Str: TStringList;
- I: LongInt;
- begin
- if Reg.OpenKeyReadOnly(Key) then
- try
- Str := TStringList.Create;
- try
-
-
-
-
- begin
- Application.ProcessMessages;
- if stop=1 then Break;
-
-
-
-
-
- if Reg.GetDataType(Str.Strings[I]) in [rdString, rdExpandString] then
- ValidData(Key, Str.Strings[I], Reg.ReadString(Str.Strings[I]));
- end;
-
-
-
- Reg.GetKeyNames(Str);
- for I := 0 to Str.Count - 1 do
- begin
- Application.ProcessMessages;
- if stop=1 then Break;
-
- if Str.Strings[I] <> '' then
- Scan(Key + '\' + Str.Strings[I]);
- end;
- finally
- Str.Free;
-
- end;
- finally
- Reg.CloseKey;
- end;
- end;
-
-
-
- procedure TRegistrySeach.ValidData( aKey, aValue, aData: String);
- var
- TmpStr: String;
- begin
- Inc(Total);
- begin
-
- TmpStr := aKey;
- if aValue <> '' then
- TmpStr := TmpStr + ' {' + aValue + '}';
- StatusBar.Panels.Items[2].Text := TmpStr;
- Application.ProcessMessages;
- end;
- if (aData = '') and (aValue <> '') then
-
- begin
- SubItems.Add(StatusBar.Panels.Items[1].Text);
- SubItems.Add(aKey);
- SubItems.Add(aValue);
- SubItems.Add(aData);
- end;
- if aData <> '' then
- if Copy(aData,1,3)='c:\' then
- if Copy(aData,Length(aData)-3,1)= '.'
- then
- if not FileExists(aData) then
-
- begin
- SubItems.Add(StatusBar.Panels.Items[1].Text);
- SubItems.Add(aKey);
- SubItems.Add(aValue);
- SubItems.Add(aData);
- end ;
- end;
 |
Вопрос задал: igoriy (статус: Посетитель)
Вопрос отправлен: 29 августа 2010, 12:00
Состояние вопроса: открыт, ответов: 0.
|
Мини-форум вопроса
Всего сообщений: 18; последнее сообщение — 31 августа 2010, 18:11; участников в обсуждении: 3.
|
Вадим К (статус: Академик), 30 августа 2010, 10:55 [#1]:
На первый взгляд, здесь нет где возникать переполнению стека. И по приложенному скриншоту это тоже видно.
Но к коду есть замечания.
- I: LongInt; - это не к чему. можно обычный Integer писать. К тому же в коде видно, что идет преобразование и здесь возникло исключение. Выведите в лог здачение Str.Count, может и проясниться что то.
- куча Application.ProcessMessages; - они только замедляют работу.
- Если в ListView добавляется больше тысячи элементов, то это сильно замедляет последующие добавления и заметно потребляет память. Лучше воспользоваться виртуальный ListView, статью о котором можно найти на этом сайте в разделе статьи.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
igoriy (статус: Посетитель), 30 августа 2010, 15:48 [#2]:
В целях эксперимента я решил в реальном времени посмотреть значения Str.Count.Бросил на форму Edit ну и в код добавил в этом цикле Edit1.Text:= IntToStr(Str.Count).И ошибка исчезла совсем.Вот тут я вообще в ауте.Как это понимать?
|
|
Вадим К (статус: Академик), 30 августа 2010, 15:52 [#3]:
Это наверное UB (неопределенное поведение). В делфи его сложно получить, но видимо Вам удалось. Думаю, стоит попробовать заменить LongIng на integer и посмотреть.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
igoriy (статус: Посетитель), 30 августа 2010, 16:05 [#4]:
Так у меня изначально и было integer это я потом уже LongInt поставил тоесть они ведут себя одинаково.А если не трудно- что такое неопределенное поведение?
|
|
Вадим К (статус: Академик), 30 августа 2010, 16:18 [#5]:
неопределенное поведение - это такой код, который может скомпилироваться по разному и компилятор имеет на это полное право.
В делфи это например такой код
str:TStringList;
begin
str := TStringList.create();
str.add('qqq');
str.free;
showmessage(inttostr(str.count));
end;
здесь мы обращаемся к удаленному объекту. Самое интересное, что в многих случаях это отработает и даже вроде нормально.
Хотя тут вообще то не совсем по правилам.
В с++ это проявляется более красиво
int j = 1;
int i = j++ + ++j;
В некоторых случаях подобные баги могут появляться и пропадать при каждой компиляции, если чуточку поменять код.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
igoriy (статус: Посетитель), 30 августа 2010, 16:24 [#6]:
Большое спасибо
|
|
bugmenot (статус: 3-ий класс), 31 августа 2010, 00:35 [#7]:
<blockquote>
I: LongInt; - это не к чему. можно обычный Integer писать
</blockquote>
в Delphi, на 32-битной платформе, ВНЕЗАПНО, типы Integer и LongInt тождественно равны. Прежде чем советовать, можно было бы и в справочник заглянуть
http://docwiki.embarcadero.com/RADStudio/en/Simple_Types
<code>
str.free;
showmessage(inttostr(str.count));
</code>
здесь нет неопределенности поведения, если диспетчер кучи обнуляет блоки - упадет, в противном случает будет всегда возвращать 0
<code>
int j = 1;
int i = j++ + ++j;
</code>
вздор, это просто выражение, на выходе i = 4, j = 3, всегда
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
|
Вадим К (статус: Академик), 31 августа 2010, 00:51 [#8]:
Цитата (bugmenot):
в Delphi, на 32-битной платформе, ВНЕЗАПНО, типы Integer и LongInt тождественно равны. Прежде чем советовать, можно было бы и в справочник заглянуть
http://docwiki.embarcadero.com/RADStudio/en/Simple_Types
Вот и гляньте. там сказано "эквиваленты", это не значит "тождественно равны". И компилятор вставляет преобразование типов. Хотя они и идентичны в битовом представлении.
Цитата (bugmenot):
здесь нет неопределенности поведения, если диспетчер кучи обнуляет блоки - упадет, в противном случает будет всегда возвращать 0
А он их не обнуляет. в этом и весь цинизм. Здесь я специально разместил рядом вызов метода free и обращение к полю. в реальном коде это может быть разнесено и возвращать может не ноль, а что "в памяти на ячейку ляжет". При чем я написал, что это не совсем неопределенное поведение.
Цитата (bugmenot):
вздор, это просто выражение, на выходе i = 4, j = 3, всегда
Вы уверенны? В стандарте языка программирования C++ есть понятие точек следования (по-английски — sequence points).
Почитайте и поймете, что Ваши варианты - это лишь один с вариантов.
компилятор вправе вначале увеличить второй j на единицу, потом сложить. и лишь потом ещё раз увеличить на единицу. Поэтому будет 3 и 3. А как именно будет - тут как скомпилируются.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
bugmenot (статус: 3-ий класс), 31 августа 2010, 00:53 [#9]:
Чорт, я так увлекся этими феерическим гаданиями, что забыл указать:
* слева вверху ответ почему stack overflow, окно call stack плотно набито рекурсивными вызовами
* которые используют стек, который в win32 большой, но не бесконечный, а в данном случае
* строковые параметры процедур передаются по значению
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
|
bugmenot (статус: 3-ий класс), 31 августа 2010, 03:06 [#10]:
Насчет префикса и постфикса - не уверен, не плюсист. Так что забег вокруг этого выражения придется отложить до завтра, когда я буду точно знать в соответствии с каким стандартом будет 3, а в соответствии с каким - 4, и какой из них - правильный™. Программирование - наука точная, и насчет следующего я не уверен, а убежден:
<blockquote>
там сказано "эквиваленты", это не значит "тождественно равны".
</blockquote>
Здесь разница между fundamental и generic типами.
<blockquote>
И компилятор вставляет преобразование типов.
</blockquote>
Нет, не вставляет, нужно доказательство. И вообще тайпкасты в Паскале просты и прямолинейны за исключением managed types.
<blockquote>
Здесь я специально разместил рядом вызов метода free и обращение к полю. в реальном коде это может быть разнесено и возвращать может не ноль, а что "в памяти на ячейку ляжет". При чем я написал, что это не совсем неопределенное поведение.
</blockquote>
это не поле, там не всё так просто, но сути не меняет. если будет между деструктором и вызовом GetCount куча будет перезаписана, то это будет примерно аналогично
<code>
var foo: Pointer;
begin TForm(foo).ShowModal;
</code>
а отнюдь не получению мусорных значений, вот для FreeAndNil это - годный пример
И да, ставлю на неумение передавать параметры, хотя создавать поле типа ListView с именем Результаты и пробовать не стану из принципа
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
|
Вадим К (статус: Академик), 31 августа 2010, 10:27 [#11]:
Цитата (bugmenot):
с именем Результаты
Так стало возможно в последних дельфях, кажется с 2007.
Цитата (bugmenot):
Программирование - наука точная,
Конечно точная. И как раз это разрешает компилятору чудить
Цитата (bugmenot):
это не поле, там не всё так просто, но сути не меняет. если будет между деструктором и вызовом GetCount куча будет перезаписана, то это будет примерно аналогично
а реализацию метода GetCount смотрели?
function TStringList.GetCount: Integer;
begin
Result := FCount;
end;
И компилятор имеет законное право соптимизировать это дело.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
igoriy (статус: Посетитель), 31 августа 2010, 11:00 [#12]:
Ребят!Спасибо конечно всем.Я понимаю что вы программисты,но я то простой смертный.И нам бы как то бы все это попроще бы.
|
|
bugmenot (статус: 3-ий класс), 31 августа 2010, 13:10 [#13]:
<blockquoute>
Так стало возможно в последних дельфях, кажется с 2007.
</blockqoute>
Категорически этого не приемлю, возможно экономит время на выдумывание хорошего имени для идентификатора, зато потом убивает на порядок больше на переключение раскладок. Это не говоря о том, что код становится похож на 1Сные ужасы.
<blockquote>
а реализацию метода GetCount смотрели?
</blockquote>
Объявление смотрел VMT благополучно перезапишется и всё упадет при первом обращении.
До префиксов-постфиксов пока еще руки не дошли...
<blockquote>
я то простой смертный.И нам бы как то бы все это попроще бы
</blockquote>
Я конечно захватил твой тред, но про передачу строковых параметров по значению еще вчера сказал
дОлжно быть procedure P(const S: string)
Поправил? Помогло?
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
|
Вадим К (статус: Академик), 31 августа 2010, 14:15 [#14]:
кириллические идентификаторы - это ещё ничего. а вот есть на арабском... вот это улёт.
Цитата (bugmenot):
Объявление смотрел  VMT благополучно перезапишется и всё упадет при первом обращении.
не факт. перезаписаться может "очень удачно".
о точках следования советую прочитать вот это к примеру http://alenacpp.blogspot.com/2005/11/sequence-points.html
Галочка "подтверждения прочтения" - вселенское зло.
|
|
igoriy (статус: Посетитель), 31 августа 2010, 16:55 [#15]:
А насчет кириллические идентификаторы - это я когда delphi 2010 поставил просто прикалывался так.Тоесть потом все нормально написал - а вот Вам старый код нечаянно послал.
|
|
Вадим К (статус: Академик), 31 августа 2010, 17:12 [#16]:
Такс, старый послал. Нужно слать актуальный!
Галочка "подтверждения прочтения" - вселенское зло.
|
|
igoriy (статус: Посетитель), 31 августа 2010, 17:17 [#17]:
Ну ивиняйте дядьку,случайно вышло.Настоящий - то же самое только без кириллици.
|
|
bugmenot (статус: 3-ий класс), 31 августа 2010, 18:11 [#18]:
Да ну старые, если бага пофиксилась то и ладно.
C++ на хинди, по нашему только пунктуация - http://govnokod.ru/3408
<blockquote>
не факт. перезаписаться может "очень удачно".
</blockquote>
Ну, скажем, вероятность отлична от нуля, а дальше комбинаторику не возьмусь оценивать, вдруг метеоритом зашибёт пока считаю 
А я уже первоисточник упиратил и признаю свою ненормативную неопределенную неправоту (Annex C ISO/IEC 9899 - ненормативен, отсюда и quirk`и компиляторов, как же хорошо программировать на языке, в котором операторы можно свести в таблицу с приоритетами и ассоциативностью)
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|