Вверх ↑
Этот топик читают: Гость
Ответов: 3889
Рейтинг: 362
#1: 2011-11-17 09:08:55 ЛС | профиль | цитата
Посмотрел на работе на другой системе (без DEP), другим дебаггером, подтвердил на практике подозрение на DriveBox и на то, что кто-то портит стек. Сперва объясню, почему у кого-то работает, у кого-то - нет. В зависимости от количества установленных программ, размера памяти, количества, версий подгруженных библиотек и т.п., распределение адресного пространства варьируется, по-этому у кого-то "под горячую руку" попадает "безобидная" область памяти, у кого-то - защищённая (получаем исключение по доступу к памяти), у кого-то - стек (получаем букет невероятных глюков в неожиданных местах, даже некоторые дебаггеры такое не любят, вернее, дебаггеру мешает DEP).

THIDriveBox -> system.LStrCat3 -> system.move -> порча стека -> фатальная ошибка
------------ Дoбавленo в 09.08:
А вот и уточнённое "место преступления":
hiDriveBox.pas - строка 396

#pas
VolList.Items[Control.CurIndex] := dspc + GetLabelDisk(Drv[1], False);


карма: 1

1
Голосовали:CriDos
vip
#1.1контекстная реклама от партнеров
Разработчик
Ответов: 26061
Рейтинг: 2120
#2: 2011-11-17 09:15:42 ЛС | профиль | цитата
1nd1g0 писал(а):
А вот и уточнённое "место преступления":

Ну, положим, на эту строку у меня уже давно подозрение закралось. Но вот как корректно избавиться от возможного краха, не имяя возможности повторить его
карма: 22

0
Ответов: 3889
Рейтинг: 362
#3: 2011-11-17 10:11:01 ЛС | профиль | цитата
Кстати, строковые функции, которые используются при склеивании строк библиотекой system (LStrCat) сам разработчик ОС не рекомендует использовать категорически ссылаясь на то, что работают они часто через стек и используют устаревший и очень опасный метод работы с пределами данных - самостоятельный перехват ошибок доступа к памяти. Причём обрабатывают ошибки молча, например, при нехватке буфера функция возвратит кусок недоделанной строки без маркера конца. В итоге, наше приложение, читая, скажем, название раздела, доходит до конца буфера, пытается читать дальше и система его убивает за попытку доступа к чему не положено. А при записи ещё серьёзнее т.к. за строкой (которая часто лежит на стеке) могут быть важные данные и адреса возврата. То есть опять же получаем вылет по DEP или доступу к недопустимым адресам памяти. Так что не все ошибки в наших силах предугадать иили исправить, многие потенциально опасные места заложены там, где их совсем не ждут.
карма: 1

0
Разработчик
Ответов: 26061
Рейтинг: 2120
#4: 2011-11-17 10:30:48 ЛС | профиль | цитата
А если список заведомо сделать на полное количество устройств. те вместо вот этого


  for Ch := 'a' to 'z' do
begin
if LongBool(DrivesMask and 1) then
begin
if _prop_UpperCharInBox then
Control.Add('[-' + UpperCase(Ch) + '-]')
else
Control.Add('[-' + Ch + '-]');
VolList.Add('');
end;
DrivesMask := DrivesMask shr 1;
end;
сделать вот это

  for Ch := 'a' to 'z' do
begin
if LongBool(DrivesMask and 1) then
begin
if _prop_UpperCharInBox then
Control.Add('[-' + UpperCase(Ch) + '-]')
else
Control.Add('[-' + Ch + '-]');
end;
VolList.Add('');
DrivesMask := DrivesMask shr 1;
end;
Складываетс впечетление, что VolList.Items[] обращается к строке, которой нет

------------ Дoбавленo в 10.30:
Или вот тут поставить защиту, вместо вот этого


  for Idx := 0 to Ctl.Count - 1 do
begin
D.VolList.Items[Idx] := dspc + GetLabelDisk(Ctl.Items[Idx][3], False);
Vol := Ctl.Items[Idx] + D.VolList.Items[Idx];
if WD < Ctl.Canvas.TextWidth(Vol) then
WD := Ctl.Canvas.TextWidth(Vol);
end;
как-то так

  for Idx := 0 to Ctl.Count - 1 do
if idx < D.VolList.Count then
begin
D.VolList.Items[Idx] := dspc + GetLabelDisk(Ctl.Items[Idx][3], False);
Vol := Ctl.Items[Idx] + D.VolList.Items[Idx];
if WD < Ctl.Canvas.TextWidth(Vol) then
WD := Ctl.Canvas.TextWidth(Vol);
end;

карма: 22

0
Ответов: 1841
Рейтинг: 369
#5: 2011-11-17 10:40:47 ЛС | профиль | цитата
nesco, с обоими вариантами ошибка...
карма: 1
0
Разработчик
Ответов: 26061
Рейтинг: 2120
#6: 2011-11-17 10:52:54 ЛС | профиль | цитата
CriDos писал(а):
с обоими вариантами ошибка...

Значит ошибка где-то в другом месте. А так как я не могу ее повторить уже и на другой машине, то это напоминает тыкание слепых котят
------------ Дoбавленo в 10.52:
Попробуй сделать так


D.VolList.Items[Idx] := ';
Потом вот так

D.VolList.Items[Idx] := dspc';

Черт с ней, с неправильной строкой, исчезнет ли ошибка
карма: 22

0
Ответов: 1841
Рейтинг: 369
#7: 2011-11-17 10:56:30 ЛС | профиль | цитата
nesco писал(а):
исечзнет ли ошибка

неа
------------ Дoбавленo в 10.56:
nesco писал(а):
D.VolList.Items[Idx] := dspc';


C:Program FilesHiAsm_AltBuildElementsdelphicodehiDriveBox.pas(202) Error: Missing operator or semicolon
карма: 1
0
Разработчик
Ответов: 26061
Рейтинг: 2120
#8: 2011-11-17 11:03:31 ЛС | профиль | цитата
Там лишний символ затесался не в тему


D.VolList.Items[Idx] := dspc;

CriDos писал(а):
неа

А это уже интересно. Выходит, что ошибка где-то в другом месте
карма: 22

0
Ответов: 1841
Рейтинг: 369
#9: 2011-11-17 11:10:57 ЛС | профиль | цитата
nesco, я уже почти пол исходника задокументировал, а рантайм всё вылетает и вылетает...

code_25816.txt
------------ Дoбавленo в 11.10:
nesco писал(а):
D.VolList.Items[Idx] := dspc;

так же
карма: 1
0
файлы: 1code_25816.txt [16.7KB] [443]
Разработчик
Ответов: 26061
Рейтинг: 2120
#10: 2011-11-17 11:12:08 ЛС | профиль | цитата
CriDos писал(а):
я уже почти пол исходника задокументировал, а рантайм всё вылетает и вылетает...

Спокойствие, только спокойствие (с)
Жук залез куда-то в другое место и тихо там сидит
карма: 22

0
Ответов: 1841
Рейтинг: 369
#11: 2011-11-17 11:17:07 ЛС | профиль | цитата
ага, после того как задокументировал содержимое процедуры procedure THIDriveBox.UpdateDriveBox;
приложение стало запускаться)
code_25817.txt
карма: 1
0
файлы: 1code_25817.txt [832B] [446]
Ответов: 3889
Рейтинг: 362
#12: 2011-11-17 11:30:38 ЛС | профиль | цитата
nesco писал(а):
Выходит, что ошибка где-то в другом месте

Нефатальная ошибка из другого места действительно может приводить к фатальной ошибке в строке, которую я указал. Пока лишь могу лишь уверить, что последнее, что делал процесс перед смертью - обращался к LStrCat3 внутри system с целью приклеить два пробела (та самая константа dspc) к конкретной строке, то есть выполнял оператор "+", а уж по какой причине вылетает (например, недупустимый индекс, пустая строка и т.п.) - дело другое.
------------ Дoбавленo в 11.30:
CriDos писал(а):
содержимое процедуры procedure THIDriveBox.UpdateDriveBox;

Для справки, это бинарно соседствующие процедуры и данные (структуры, строки и т.п.) у них тоже рядом лежат, возможно, кто-то другой портит адресное пространство, просто у Вас он попадает чуть "выше" по адресам, чем у меня и ошибка проявляется в этих процедурах, а у nesco вообще не проявляется. А дело может крыться в каком-нибудь потоке, подгружающейся библиотеке и т.п.
карма: 1

0
Разработчик
Ответов: 26061
Рейтинг: 2120
#13: 2011-11-17 11:32:42 ЛС | профиль | цитата
CriDos писал(а):
приложение стало запускаться

Попробуй поставить в методе THIDriveBox.UpdateDriveBox ремарку только на

  SetDriveName(Drv);
карма: 22

0
Ответов: 3889
Рейтинг: 362
#14: 2011-11-17 11:32:55 ЛС | профиль | цитата
CriDos, можно посмотреть Ваш exe (естественно, несжатый).
карма: 1

0
Ответов: 1841
Рейтинг: 369
#15: 2011-11-17 11:35:10 ЛС | профиль | цитата
nesco писал(а):
SetDriveName(Drv);

я только хотел написать про него
ошибка пропала
карма: 1
0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)