Здравствуйте.
Есть приложение, прекрасно работающее на ХР. Но под Вистой/семеркой вылетает при запуске. Поручили мне разобраться в чем проблема. Оказалось, под отладчиком программа запускается и работает! Но стоит только запустить вне отладчика - и крэш. Посоветуйте - как отладить приложение? Как найти причину, или хотя бы предполагаемое место возникновения ошибки?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
18-04-2011 07:13 | Комментарий к предыдущим ответам
Моральный_ehjl
Заголовочники для GDI+ мы используем от progdigy, только немного переделанные (ничего кардинального - разные мелочи, например, добавили методы загрузки из "родного" TStream/ресурсов, вместо возвращения кода ошибки заставили генерировать исключения, добавили кое-какие функции типа ColorToGpColor ну и так далее)
Спасибо огромное всем отвечавшим. В поисках ответа на свой вопрос нашел 1 в 1 такую же ситуацию: http://stackoverflow.com/questions/2612671/gdi-crashes-when-loading-png-from-istream
И действительно, оказалось что это бага нето Висты, нето Дельфи. В реализации TStreamAdapter есть маленький изьян - в TStreamAdapter.Stat не полностью инициализируется структура TStatStg, в частности pwcsName - если был передан флаг STATFLAG_NONAME, там должен быть nil, но в Висте там оказывался мусор (при запуске из среды под дебаггером магическим образом инициализировался в nil), но мало того - Виста пыталась этот мусор както использовать, что вызывало повреждение кучи.
Заплатка:
type
TStreamAdapter = class(Classes.TStreamAdapter)
public
function Stat(out statstg: TStatStg;
grfStatFlag: Longint): HRESULT; override; stdcall;
end;
{ TStreamAdapter }
function TStreamAdapter.Stat(out statstg: TStatStg;
grfStatFlag: Integer): HRESULT;
begin
Result := inherited Stat(statstg, grfStatFlag);
if (Result = S_OK) and (grfStatFlag and STATFLAG_NONAME = STATFLAG_NONAME) then
statstg.pwcsName := nil;
end;
В таком варианте всё работает отлично.
P.S. Не знаю, может есть смысл в подводные камни отправить? Как думаете?
to ~AQUARIUS~
Используете Delphi XE со стандартными хидерами GDI+?
Была очень похожая проблема, но с WindowsXP (на Win7 не проверял), на SP3 работало, на SP2 вываливалось AV при загрузке png файла, решил проблему использованием оригинальных хидеров: http://www.progdigy.com/files/gdiplus.zip
Нашел где зависает - при вызове GdipLoadImageFromStream из gdiplus.dll, на загрузке png-картинки. Теперь бы разобраться - почему не зависает под дебаггером, какое это имеет отношение к ntdll.dll, ну и самое главное - что с этим делать...
MrShoor
Да, программа многопоточная, но потоки создаются только потом - после нажатия на некоторые кнопки.
А вообще больше данных давайте
С удовольствием - если б были. Месаджбоксы расставлял в первую очередь - первой строкй в .дпр, на создание форм; ни один не сработал, очевидно, зависает где-то на инициализации модулей. Кстати, пытался совсем убрать код, отвечающий за загрузку ресурсов, из initialization - программа запустилась, правда мне непонятно, как это тогда в ХР работало без проблем. Привожу проблемный код:
class procedure TResources.LoadResources;
var
hLib: HMODULE;
hIco: HICON;
res: TResourceStream;
img: TGPImage;
g: TGPGraphics;
begin
if not Assigned(FButtons) then FButtons := TBitmap.Create;
if not Assigned(FPanels) then FPanels := TBitmap.Create;
if not Assigned(FShadow) then FShadow := TGPImage.Create;
if not Assigned(FJpeg) then FJpeg := TIcon.Create;
if not Assigned(FPng) then FPng := TIcon.Create;
if not Assigned(FGif) then FGif := TIcon.Create;
hLib := HInstance; //LoadLibrary(PChar(ExtractFilePath(ParamStr(0)) + sMediasDll));
if hLib = 0 then Exit;
try
hIco := LoadImage(hLib, 'JPEG', IMAGE_ICON, 48, 48, LR_COLOR or LR_COPYFROMRESOURCE);
FJpeg.Handle := CopyImage(hIco, IMAGE_ICON, 0, 0, LR_COPYDELETEORG);
Программа многопоточная? Если нет - то раскидайте мессаджбоксы по коду, и локализуйте место где виснет. А вообще больше данных давайте. Этих данных явно недостаточно чтобы хоть как то подсказать.
В секции инициализации одного из модулей был код, который загружал длл, доставал из нее некоторые ресурсы и выгружал. Перенес эти ресурсы в .ехе, теперь программа не вылетает, но выснет, загружая процессор на 90-100%. Опять же, при запуске из среды по F9 всё хорошо
Системное сообщение об ошибке; тип - APPCRASH; модуль с ошибкой - ntdll.dll; штампы времени; всё :-(
При запуске по F9 из среды всё работает - ни исключений, ни тем более крэша
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.