Yes, tried it with both virtual (Microsoft's Print to PDF) and physical printers and the problem occurs regardless of which one is used. What bothers me now is why I can't make it crash in XIDE in Debug mode.Chris wrote: ↑Thu Apr 25, 2024 8:33 am Hi Michal,
Thanks for the very good sample, but unfortunately I could not reproduce the problem here, all 65 pages are always printed ok here. Does the problem happen with any printer driver? Even when selecting a pdf driver, like PDF creator or Microsoft's print to pdf driver from Windows? To be honest that's what I used as well, wanted to avoid wasting 65 pages of paper..
ReportPro 3.60 for XSharp 2.60 memory exception
- Michal Rajnoha
- Posts: 23
- Joined: Wed Sep 29, 2021 6:57 am
Re: ReportPro 3.60 for XSharp 2.60 memory exception
Re: ReportPro 3.60 for XSharp 2.60 memory exception
Hi Michal,
Memory corruption issues can be like that, when running through the debugger some memory locations may be different, preventing the underlying problem to expose itself. What OS are you using and what is the .Net Framework version installed? Also since I don't have your email address, can you please send me a short email and I will send you a link to a set of slightly newer RP3 files, they might make a difference as we fixed another issue that could be related recently.Michal Rajnoha wrote: ↑Thu Apr 25, 2024 8:46 amYes, tried it with both virtual (Microsoft's Print to PDF) and physical printers and the problem occurs regardless of which one is used. What bothers me now is why I can't make it crash in XIDE in Debug mode.Chris wrote: ↑Thu Apr 25, 2024 8:33 am Thanks for the very good sample, but unfortunately I could not reproduce the problem here, all 65 pages are always printed ok here. Does the problem happen with any printer driver? Even when selecting a pdf driver, like PDF creator or Microsoft's print to pdf driver from Windows? To be honest that's what I used as well, wanted to avoid wasting 65 pages of paper..
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
- Michal Rajnoha
- Posts: 23
- Joined: Wed Sep 29, 2021 6:57 am
Re: ReportPro 3.60 for XSharp 2.60 memory exception
Chris wrote: ↑Thu Apr 25, 2024 9:18 am Memory corruption issues can be like that, when running through the debugger some memory locations may be different, preventing the underlying problem to expose itself. What OS are you using and what is the .Net Framework version installed? Also since I don't have your email address, can you please send me a short email and I will send you a link to a set of slightly newer RP3 files, they might make a difference as we fixed another issue that could be related recently.
We tried it on Windows 11 and Windows 10.
2 PCs where X# is installed and 1 with only redistributables. All have the same issue.
The latest version of .NET Framework we use is 4.8.1.
I will send the email soon.
Re: ReportPro 3.60 for XSharp 2.60 memory exception
Greetings,
We observe the exact same problem. It turns out that printing through the cPrinter class crashes with memory errors whenever we compile Classmate with the "Build/Optimize" flag. It only happens when using the printer DC, print preview is not affected. Disabling Optimize in Release builds (or using Debug builds) stops the crashes.
Is this a compiler bug or a Classmate bug? Is there a known fix?
We observe the exact same problem. It turns out that printing through the cPrinter class crashes with memory errors whenever we compile Classmate with the "Build/Optimize" flag. It only happens when using the printer DC, print preview is not affected. Disabling Optimize in Release builds (or using Debug builds) stops the crashes.
Is this a compiler bug or a Classmate bug? Is there a known fix?
Code: Select all
Anwendung: WorkSuite.exe
Frameworkversion: v4.0.30319
Beschreibung: Der Prozess wurde aufgrund einer unbehandelten Ausnahme beendet.
Ausnahmeinformationen: System.AccessViolationException
bei VOWin32APILibrary.Functions.DrawText(Void*, IntPtr, Int32, VO._winRECT*, UInt32)
bei Classmate.cHDC.DrawText(System.String, Int32, XSharp.__Float, XSharp.__Float, XSharp.__Float, XSharp.__Float, UInt32)
bei PP_Server.PrintString(XSharp.__Usual[])
bei PP_Server.PrintElement(XSharp.__Usual[])
bei PP_Server.PrintSection(XSharp.__Usual[])
bei PP_Server.PrintPageBody()
bei Classmate.cPrinter._PrintPage()
bei Classmate.cPrinter._PrintDoc()
bei Classmate.cPrinter._PrintStart()
bei Classmate.cPrintMsgDialog.OnTimer(Classmate.cEvent)
bei Classmate.cWindow.Dispatch(Classmate.cEvent)
bei Classmate.cBaseDialog.Dispatch(Classmate.cEvent)
bei Classmate_Gui.Functions._cDialogProc(Void*, UInt32, UInt32, Int32)
bei VOWin32APILibrary.Functions.IsDialogMessage(Void*, VO._winMSG*)
bei Classmate.cWindow._PreProcessMessage(VO._winMSG*)
bei Classmate.cDialog._ModalExec()
bei Classmate.cDialog.Show(Int32)
bei Classmate.cPrintMsgDialog.Show(Int32)
bei Classmate.cPrinter.Print()
bei PP_Server.Print(XSharp.__Usual[])
bei SQLRuntime.Functions.PPC_Install(XSharp.__Usual[])
bei DynamicClass.PPC_Install(RTE_L(39),NIL,ARR_Get(RTE_L(14),4),RTE_L(11),RTE_L(12),ARR_Get(RTE_L(14),5))(RTE_L(39),NIL,ARR_Get(RTE_L(14),4),RTE_L(11),RTE_L(12),ARR_Get(RTE_L(14),5))(XSharp.__Usual[])
bei XSharp.MacroCompiler.UsualMacro.MacroCodeblock.Eval(XSharp.__Usual[])
bei XSharp.RT.Functions.Eval(XSharp.ICodeblock, XSharp.__Usual[])
bei XSharp.RT.Functions.MExec(XSharp.Codeblock)
bei SQLRuntime.Functions.RTE_ExecMacroP(XSharp.__Usual, XSharp.__Usual, XSharp.__Usual)
bei SQLRuntime.Functions.RTE_Exec(XSharp.__Usual[])
bei SQLRuntime.Functions.RTE_Func(XSharp.__Usual[])
bei DynamicClass.RTE_Func("SYS.STDFForm",{"QUOTE","QUOTE_KOPF","QUOTE_HPOS","QUOTENR",DWN_Selected(),""})("SYS.STDFForm",{"QUOTE","QUOTE_KOPF","QUOTE_HPOS","QUOTENR",DWN_Selected(),""})(XSharp.__Usual[])
bei XSharp.MacroCompiler.UsualMacro.MacroCodeblock.Eval(XSharp.__Usual[])
bei XSharp.RT.Functions.Eval(XSharp.ICodeblock, XSharp.__Usual[])
bei XSharp.RT.Functions.MExec(XSharp.Codeblock)
bei SQLRuntime.Functions.RTE_ExecMacroP(XSharp.__Usual, XSharp.__Usual, XSharp.__Usual)
bei SQLRuntime.Functions.RTE_Exec(XSharp.__Usual[])
bei MN_Object.Execute(XSharp.__Usual[])
bei MN_Object.mnuODIExec(XSharp.__Usual[])
Ausnahmeinformationen: System.Reflection.TargetInvocationException
bei System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)
bei System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[])
bei System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
bei XSharp.RT.OOPHelpers.SendHelper(System.Object, System.Reflection.MethodInfo, XSharp.__Usual[], XSharp.__Usual ByRef, Boolean)
bei XSharp.RT.OOPHelpers.SendHelper(System.Object, System.String, XSharp.__Usual[], XSharp.__Usual ByRef, Boolean)
bei XSharp.RT.OOPHelpers.DoSend(System.Object, System.String, XSharp.__Usual[], System.String)
bei XSharp.RT.Functions.Send(XSharp.__Usual, XSharp.__Usual, XSharp.__Usual[])
bei Classmate.cMenu._ProcessCommandMsg(Classmate.cEvent)
bei Classmate.cWindow.OnCommand(Classmate.cEvent)
bei WN_Dialog.OnCommand(Classmate.cEvent)
bei Classmate.cWindow.Dispatch(Classmate.cEvent)
bei Classmate.cBaseDialog.Dispatch(Classmate.cEvent)
bei WN_Dialog.Dispatch(Classmate.cEvent)
bei Classmate_Gui.Functions._cDialogProc(Void*, UInt32, UInt32, Int32)
bei VOWin32APILibrary.Functions.IsDialogMessage(Void*, VO._winMSG*)
bei WN_Dialog._PreProcessMessage(VO._winMSG*)
bei Classmate.cApp.Exec()
bei cWorkSuite.Start(XSharp.__Usual[])
Ausnahmeinformationen: System.Reflection.TargetInvocationException
bei System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)
bei System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[])
bei System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
bei XSharp.RT.OOPHelpers.SendHelper(System.Object, System.Reflection.MethodInfo, XSharp.__Usual[], XSharp.__Usual ByRef, Boolean)
bei XSharp.RT.OOPHelpers.SendHelper(System.Object, System.String, XSharp.__Usual[], XSharp.__Usual ByRef, Boolean)
bei XSharp.RT.OOPHelpers.DoSend(System.Object, System.String, XSharp.__Usual[], System.String)
bei XSharp.RT.Functions.Send(XSharp.__Usual, XSharp.__Usual, XSharp.__Usual[])
bei Classmate_Gui.Functions.CmStart(XSharp.__Symbol)
bei WorkSuite.Exe.Functions.Start()
Re: ReportPro 3.60 for XSharp 2.60 memory exception
I am afraid that building without the optimize flag is the only solution for now, that fixed the problem Michal reported, too. Unfortunately so far we haven't been able to reproduce the problem locally, so it is very difficult to find what's causing it.
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
Re: ReportPro 3.60 for XSharp 2.60 memory exception
This didn't fix Michal's problem unfortunately, but it's still worth a try. Please open the file \Classmate, Gui\Printer\Printer, Printer.prg
and change the code in METHOD _PrintDoc() from
Code: Select all
LOCAL dAbort AS _AbortProc32Delegate
LOCAL pAbort AS IntPtr
dAbort := _AbortProc32Delegate{ NULL, @_AbortProc32() }
pAbort := Marshal.GetFunctionPointerForDelegate( (System.Delegate) dAbort )
Code: Select all
STATIC LOCAL dAbort := _AbortProc32Delegate{ NULL, @_AbortProc32() } AS _AbortProc32Delegate
STATIC LOCAL pAbort := Marshal.GetFunctionPointerForDelegate( (System.Delegate) dAbort ) AS IntPtr
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
Re: ReportPro 3.60 for XSharp 2.60 memory exception
Well, we changed these variables to STATIC and it fixed the problem. Release builds with compiler optimization for the entire solution can now print documents without crashing. I've only done some preliminary testing, but it looks good so far. Beforehand, it basically couldn't print at all.
It's strange that this did not work for Michal, as his problem appears to be identical. When running the faulty release build in the debugger, it literally tells me that a delegate of type "Classmate.Gui!Classmate._AbortProc32Delegate::Invoke" has been garbage collected too early.
Would you say it's required for all Windows API callback functions to have their delegates and function pointers static?
Thanks and best regards
It's strange that this did not work for Michal, as his problem appears to be identical. When running the faulty release build in the debugger, it literally tells me that a delegate of type "Classmate.Gui!Classmate._AbortProc32Delegate::Invoke" has been garbage collected too early.
Would you say it's required for all Windows API callback functions to have their delegates and function pointers static?
Thanks and best regards
Re: ReportPro 3.60 for XSharp 2.60 memory exception
Oh my, I just realized that when I sent the "fixed" dlls to Michal, I forgot to actually include the STATIC keyword! Really thanks for the heads up, Michal I will resend the files and they should fix the problem for you, with the release dlls, too.
Regarding WinAPI functions in general, you just have to make sure that the delegate they use is still active when they are called and when they call back your own code. Delegates are like normal objects, and when they go out of scope, the GC can collect them, like other objects. And the .Net GC does not manage WinAPI code, so it does not know that a delegate is used in them.
So one way is to make the LOCAL declaration of the delegate STATIC (so never goes out of scope), or make it a class variable (but of course that object itself must not get collected before thw WinAPI callbacks either!), or if you are sure that the current entity (method/function etc) will be still executing when the WinAPI makes the call(s), you can put at the end of it a
GC.KeepAlive(object_to_make_sure_is_not_collected)
to make sure the object is still alive when reaching that line of code.
Regarding WinAPI functions in general, you just have to make sure that the delegate they use is still active when they are called and when they call back your own code. Delegates are like normal objects, and when they go out of scope, the GC can collect them, like other objects. And the .Net GC does not manage WinAPI code, so it does not know that a delegate is used in them.
So one way is to make the LOCAL declaration of the delegate STATIC (so never goes out of scope), or make it a class variable (but of course that object itself must not get collected before thw WinAPI callbacks either!), or if you are sure that the current entity (method/function etc) will be still executing when the WinAPI makes the call(s), you can put at the end of it a
GC.KeepAlive(object_to_make_sure_is_not_collected)
to make sure the object is still alive when reaching that line of code.
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
Re: ReportPro 3.60 for XSharp 2.60 memory exception
One more thing, when you rebuild RP3, please open the file \Include\Rp3.vh and set the DESIGNENV #define to FALSE, for the dlls that you will be referencing in your application (for when you want to build/run the standalone RP3 designer, then you need to have it set to TRUE again). Without doing this (when it's on TRUE), the build process includes some additional code which might interfere with the rest of your code, like changing things like SetEpoch(), separators etc.
In a future RP3 release, we will make separate projects for the designer and reference dlls, so those will be in different output locations when you build them.
In a future RP3 release, we will make separate projects for the designer and reference dlls, so those will be in different output locations when you build them.
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu