You are not logged in.
Pages: 1
Hi,
using Delphi XE and SynPDF v1.18 on Windows 10:
PDF creation works fine but after closing my application I get runtime error 216.
I traced it down to the finalization of unit SynGdiPlus.
finalization
Gdip.Free;
Windows.DeleteCriticalSection(GdipCS);
end.
Gdip.Free causes the problem, so Windows.DeleteCriticalSection(GdipCS) is skipped when debugging.
Any help appreciated.
Regards,
Tom
Offline
I don't get which kind of problem Gdip.Free may trigger, and never seen it in practice...
Do you have any more information about the context?
Most of the time, a "Runtime error 216" comes from a wrongly used of library resources in the program, IIRC.
An exception is probably raised in the initialization section of your code, or the framework code.
See https://stackoverflow.com/a/35747477/458259
Offline
This may be due to use the SynPDF in a DLL.
To avoid error you can call FreeAndNil(Gdip) before DLL will be unloaded.
Offline
Thanks for your help.
I'm using the PDF engine together with the "Print Preview" component (DelphiArea.com website).
I included the {$DEFINE SYNOPSE} compiler directive in the project options.
This should be enough for the Print Preview component to take care of everything if I understood correctly.
In my own project units I don't have any link to SynPDF.
Printing a PDF works fine, the error occurs after closing the application.
If I remove the compiler directive (in other words, when I don't use the PDF engine), no error occurs.
Where should I put the "FreeAndNil(Gdip)"?
Offline
Are you building/working with an ISAPI?
In this case your initializations/finalizations can be called for each execution (thread) but global vars are shared across the DLL so gdip could be freed when it is already free.
try to change finalization with:
finalization
if Gdip<>nil then
FreeAndNil(Gdip);
Windows.DeleteCriticalSection(GdipCS);
end.
Last edited by MtwStark (2018-03-28 10:04:51)
Offline
Yesterday I posted my question on the DelphiArea forum but no answer yet.
My application is a VCL Forms application.
I din't try mORMotReport.pas since I'm using Print Preview for many years now. I prefer to keep using Print Preview if possible.
I changed the finalization without success.
If I debug trace into (F7) the finalization I enter the TGDIPlus.Destroy destructor.
fStartupHook.UnHook(fStartupHookToken) is the command that causes the problem.
destructor TGDIPlus.Destroy;
begin
if fToken<>0 then begin
if Assigned(fStartupHook.UnHook) then // may be nil e.g. for Win64
fStartupHook.UnHook(fStartupHookToken);
Shutdown(fToken);
fToken := 0;
end;
UnLoad;
inherited Destroy;
end;
Offline
I distributed the application on a Windows 7, same problem.
Offline
Looking the Gdiplus Startup Output structure documentation it says that using the wrong token in the unhook function will cause resource leaks, cleaned up when the process exits.
This should not produce a runtime error.
I think the problem could be in the TGDIPlus.Create, maybe the token received in the hook function was invalid?
The hook function should returns a status (TGdipStatus) but it is not tested in TGDIPlus.Create
it is possible that the call of Startup(fToken,Input,fStartupHook) returns an error (<>stOk) but puts something dirt in fStartupHook?
In this case during the Destroy the fStartupHook.UnHook could result Assigned (<>nil) but invalid.
Try to clear the fStartupHook record when Startup fails in the TGDIPlus.Create:
if Startup(fToken,Input,fStartupHook)<>stOk then begin
FillChar(fStartupHook, SizeOf(fStartupHook), 0); // MTW 2018-03-28 - Be sure Hook/UnHook are unassigned
fToken := 0;
UnLoad;
exit;
end;
Offline
Thanks for your suggestion.
It didn't solve the problem.
Debugging learns me that Startup(fToken,Input,fStartupHook) = stOk. This begin-end block is not executed.
Offline
you are welcome.
Are you sure the error is raised on fStartupHook.UnHook(fStartupHookToken), and not on Shutdown(fToken)?
In any case, I think the problem could be related to gdi objects not released before the TGDIPlus.Destroy
Shutdown procedure must be called only after all gdi objects are released...
Try to place a breakpoint in TPrintPreview.Destroy, TThumbnailPreview.Destroy and TPaperPreview.Destroy and see if the runtime error is raised before the destroy of you "Print Preview" component.
If it does not release all gdi objects before destruction it could bring to this kind of problems.
I have taken a brief look into preview.pas and I see it has its own gdiplus support.. maybe the problem is a conflict between the two.
In preview.pas, I would check also TGDIPlusSubset.Create and _gdiPlus.Free in finalization (TGDIPlusSubset.Destroy)
Finally..
I'm still using Delphi 2007 so, I'm not sure about that, but I have read here that in XE2 the calls to “GdiplusStartup” and “GdiplusShutdown” are only performed if not IsLibrary is True to avoid hangs in shutdown..
Last edited by MtwStark (2018-03-29 08:43:28)
Offline
The runtime error is raised before reaching the TPrintPreview.Destroy and TPaperPreview.Destroy breakpoints.
TGDIPlusSubset.Destroy is executed before the SynPDF, SynCrypto, SynCommons and SynGDI finalization.
I made a small video showing the debugging. The runtime error itself isn't shown because only the Delphi Environment window was captured.
http://173.236.46.37/Runtime216.mp4
Offline
Try to download the last print preview source code, TGDIPlusSubset Create/Destroy are slight different, maybe this was a known problem.
Offline
This seems to do the trick! Tomorrow I do some more testing to be absolutely sure.
Thanks you so much.
Offline
you are welcome
I'm happy to hear you have solved
Offline
Pages: 1