| 
| 
 | Вопрос # 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сця, де призупинилося.
 
 |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |