Jump to content

A.M. Hoornweg

Members
  • Content Count

    446
  • Joined

  • Last visited

  • Days Won

    8

Everything posted by A.M. Hoornweg

  1. Hello all, I've noticed that an application I'm working on was behaving differently when compiled in Delphi 11 or 12. In Delphi 12 I was getting all sorts of overflows and unexpected behavior. It took me a while to figure out the cause. Now the surprising thing: The cause wasn't even in this executable I was working on, it was in a DLL that my program is using. This DLL was built with a previous version of Delphi. This particular DLL expects that a FP error such as a division by zero will throw an exception. A breaking change in Delphi 12 is that the executables it produces mask the FP exceptions. This change in behavior affects all code running in the process, including all DLLs. In other words, this DLL no longer threw exceptions where it was supposed to. My workaround was to re-enable FPU exceptions in the executable and the situation instantly went "back to normal". But it got me thinking, how does one write code that copes with both FP situations and can run safely with *any* Delphi version? Should I do something like this? Try c:=SomeHighlyComplexCalculation(); if IsNan (c) then raise eDivByZero.Create('Something went wrong'); except // the exception is triggered either automatically (Old Delphi version) or manually (New Delphi version) end; Currently, my gut feeling tells me to manually enable FPU exceptions in all my Delphi exe projects to prevent such nasty surprises in the future. I use tons of tried-and-tested DLLs written in Delphi and I really don't want them to break.
  2. It would be a can of worms for me I'm afraid. I am thinking of all my Delphi COM DLL's that expose interfaces and class factories (see image). Each interface is basically an object that can have dozens of methods so we're not talking about just a few functions, it's more like hundreds of exposed methods. And many of these methods call each other, which complicates matters further because setfpcr/restorefpcr would have to support nesting. And multi-threading would make matters even more complicated.
  3. "Take control on entry and restore on exit" would be very cumbersome in the case of DLL's written in Delphi. It would need to be done in every exposed function / method. (edit) or at least in every method that has to do with FP calculations.
  4. OK, that massively simplifies matters. My fear was that the FPCR would be a shared resource among threads.
  5. I have no way of knowing. In the distant past the FPU (80x87) used to be an expensive separate chip. I simply don't know if the fpu is now part of each cpu core.
  6. That is not what I mean, since a "context switch" is done when the scheduler switches from one thread to another (so one is halted, its state is saved and the next thread resumes after its state was restored). My question is about threads literally running simultaneously on different CPU cores, does each core always have an independent FPU + FPCR so one thread cannot jeopardize another ?
  7. Since threads run concurrently on multi-core systems, isn't the fp control state global to all threads? Or does every cpu core have its own fpu core?
  8. Sure it is documented. But it may be off the radar that existing binaries such as DLL's may suddenly behave differently if they were written in Delphi. I use some third-party DLL's that were written in Delphi.
  9. As far as I can see you can't download from that site though.
  10. A.M. Hoornweg

    Delphi 12.1 is available

    I am getting "Disconnected Session" all the time whilst working on a 64-bit project. Never had this problem in 12.0. The error dialog window contains this information: [69E0B1C0]{dbkdebugide290.bpl} Debug.TDebugKernel.msgBox (Line 5951, "Debug.pas" + 30) + $0 [2BCC6EB3]{bordbk290.dll} Unknown function at DllUnregisterServer + $5037 [2BD3B88C]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $619B4 [2BD3B90B]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $61A33 [2BD3C351]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $62479 [2BD3C5A1]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $626C9 [2BD6C3D3]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $924FB [69E0B6FD]{dbkdebugide290.bpl} Debug.TThread.DoGetCurAddr (Line 6080, "Debug.pas" + 1) + $4 [2BCD9D72]{bordbk290.dll} Unknown function at DllUnregisterServer + $17EF6 [2BD6A91D]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $90A45 [2BD3C577]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $6269F [2BD3C7E0]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $62908 [2BCC6A4B]{bordbk290.dll} Unknown function at DllUnregisterServer + $4BCF [2BD5AB32]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $80C5A [2BD5AB3C]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $80C64 [69E17AFD]{dbkdebugide290.bpl} Debug.GetNextEvent (Line 11764, "Debug.pas" + 1) + $24 [6DC6037A]{rtl290.bpl } System.@IsClass (Line 18904, "System.pas" + 1) + $8 [69E185E1]{dbkdebugide290.bpl} Debug.TDebugger.UpdateEventLog (Line 11776, "Debug.pas" + 9) + $1 [69E11931]{dbkdebugide290.bpl} Debug.TProcess.ntfyNewEventLogData (Line 9020, "Debug.pas" + 1) + $7 [2BD5B3A0]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $814C8 [2BD3B90B]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $61A33 [2BD3C577]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $6269F [2BD570FB]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $7D223 [2BD57136]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $7D25E [2BD6C4C7]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $925EF [2BCD9D72]{bordbk290.dll} Unknown function at DllUnregisterServer + $17EF6 [2BD3B8B0]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $619D8 [2BD3C7E0]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $62908 [2BCE4247]{bordbk290.dll} Unknown function at @isDbkLoggingOn$qv + $A36F [625AA5EA]{CnWizards_D120A.DLL} Unknown function at __dbk_fcall_wrapper + $788AA [6CB305FD]{vcl290.bpl } Vcl.Themes.TStyleHook.WndProc (Line 7733, "Vcl.Themes.pas" + 38) + $6 [6CC598FC]{vcl290.bpl } Vcl.Styles.TStyleEngine.HandleMessage (Line 3616, "Vcl.Styles.pas" + 20) + $C [6340DEA9]{mmx_bds23.dll} IDEEdtHooks.GetMessageHook (Line 66, "IDEEdtHooks.pas" + 7) + $12 [6279DE04]{CnWizards_D120A.DLL} Unknown function at INITWIZARD0001 + $17CC00 [6CB7392F]{vcl290.bpl } Vcl.Forms.TApplication.ProcessMessage (Line 13284, "Vcl.Forms.pas" + 25) + $1 [6CB73952]{vcl290.bpl } Vcl.Forms.TApplication.ProcessMessages (Line 13304, "Vcl.Forms.pas" + 1) + $4 [00487F2B]{bds.exe } AppMain.TAppBuilder.ApplicationActivated + $7 [6CBCD24F]{vcl290.bpl } Vcl.AppEvnts.TCustomApplicationEvents.DoActivate (Line 210, "Vcl.AppEvnts.pas" + 1) + $16 [6CBCD8ED]{vcl290.bpl } Vcl.AppEvnts.TMultiCaster.DoActivate (Line 438, "Vcl.AppEvnts.pas" + 5) + $10 [6CB72DD0]{vcl290.bpl } Vcl.Forms.TApplication.WndProc (Line 12854, "Vcl.Forms.pas" + 140) + $C [6DD8477C]{rtl290.bpl } System.Classes.StdWndProc (Line 19085, "System.Classes.pas" + 9) + $2 [6CB73927]{vcl290.bpl } Vcl.Forms.TApplication.ProcessMessage (Line 13282, "Vcl.Forms.pas" + 23) + $1 [6CB7396A]{vcl290.bpl } Vcl.Forms.TApplication.HandleMessage (Line 13312, "Vcl.Forms.pas" + 1) + $4 [6CB73CA9]{vcl290.bpl } Vcl.Forms.TApplication.Run (Line 13451, "Vcl.Forms.pas" + 27) + $3 [004D8AD2]{bds.exe } bds.bds + $DE
  11. A.M. Hoornweg

    Do you need an ARM64 compiler for Windows?

    There are ways to achieve that (passing an EMF cross-process) but yes, it would be ugly. It would be like re-inventing the RDP protocol.
  12. A.M. Hoornweg

    Do you need an ARM64 compiler for Windows?

    If you'd ask me to attempt a thing like that, I'd first look for a suitable bidirectional RPC framework. Something having capabilities like COM. COM was used by IDE's such as Visual Basic to host (in-process) VBX controls but it works across processes as well. The "helper processes" would only need to contain the designtime part of the components, at runtime they do nothing. Such an approach would move the design time components out of the address space of the IDE. Also, the "bitness" of the helper processes and the IDE would be independent from each other.
  13. A.M. Hoornweg

    Do you need an ARM64 compiler for Windows?

    My preference would be to have the component packages in separate helper processes.
  14. A.M. Hoornweg

    Do you need an ARM64 compiler for Windows?

    Please remember that all installed design time packages (BPL files) and their associated runtime packages must be compiled to the same architecture and bitness as the IDE itself. BPLs are just DLLs and the IDE loads them directly, in-process. This means that moving away from 32-bit x86 would be a huge breaking change for the deployment of third party components. Frankly, I've never understood why the design time packages are hosted in the IDE process itself because bugs in components will affect the IDE. Many of us will know the phenomenon that the IDE may throw an AV exception in some BPL when you terminate Delphi.
  15. Can't you make a read-only property out of it instead of a plain method? That way you could make it show up in the watch list of the debugger.
  16. A.M. Hoornweg

    A gem from the past (Goto)

    No need for this, the debugger has that functionality built-in: -Set a breakpoint on your corner case condition and wait until it fires -Right-click the line where you want to "go to" -Enter submenu "Debug" -Select menu item "Set next statement". The debugger will jump here when you single-step through your code.
  17. A thread using While not terminated do begin Dosomething; Sleep(xxx); end; is perfectly OK if the thread has to do something useful periodically and if xxx isn't a terribly small number. But if "Dosomething()" is merely polling for some state change to respond to, then it's rather inefficient to have this thread constantly wakeup, consume CPU time and sleep again. The "Sleep(xxx)" also limits the response time and the number of state changes that can be handled per second. For such a scenario it's much more efficient if you can wake up the thread "from the outside" ASAP when it has to react. This is where events really shine.
  18. I would personally write such a program as a service application and let it monitor messages like WM_POWERBROADCAST to log the events. This way you can be sure that the application is always running and will capture the events when they happen.
  19. Hello all, I see that the Delphi 12 source code formatter (Ctrl-D) still mutilates generic class declarations, it inserts inappropriate line feeds between keywords and ruins indentation. Is there a way to set markers in the source code that tell the formatter to skip those areas from formatting? Or can you recommend a better code formatter that handles generics properly? Have a nice day! Arthur
  20. Hello all, suppose I have a generic class that's going to be inherited. I want to give the base class a method that creates a new instance of the same object type (a class factory so to speak). How can I do that? I need to somehow tell the compiler which constructor to call. Type tSomeclass<T:iInterface>=CLass (tInterfacedObject, iSomeInterface<T>) //many methods here Procedure SomeMethod(intf: T); Function SomeFunction:T; Constructor Create(someparameters); Function CreateNewInstance:iSomeInterface<T>; end; ... Function tSomeclass<T>.CreateNewInstance:iSomeInterface<T> begin result:=Self.Classtype.Create(fSomeParameters); //Does not compile end;
  21. A.M. Hoornweg

    Create a new instance of a generic class

    Thank you! That seems to work indeed !
  22. A.M. Hoornweg

    Create a new instance of a generic class

    The reason I'm trying to achieve this is the following. I have made a generic tStreamableInterfaceList<T:iInterface> which is basically a managed Tlist<T> that implements iInterfacelist<T>. The elements are interfaces. This list object knows several special tricks such as saving its contents to XML and BSON. It can also load those elements back from such data files, which necessitates a virtual ClassFactory() method to create the correct objects "on the fly" based on the class names found in the data. So far, this all works very nicely. I wanted to enhance this list with a few LinQ-like methods such as: Function .Where(aCondition:tPredicate<T>):iInterfacelist<T>; Function .OrderBy(aCompare:tComparison<T>):iInterfacelist<T>; ... but in order to achieve that, the base class must be able to dynamically instantiate derived classes or else the resulting objects would have the base nonfunctional Classfactory() method. The "ugly" solution would be to put an abstract virtual Clone() method in the base class, but I'd very much like to avoid that.
  23. A.M. Hoornweg

    Create a new instance of a generic class

    That doesn't do the trick, because function TMyClass<T>.CloneObject: TMyClass<T>; ... will just construct an instance of the base class, I would have to re-implement that method in each derived class. With non-generic classes it is possible to achieve what I want (see below). With generics, the "class of..." syntax does not work. type SomeClassType = class of tSomeClass; tSomeClass = class protected SomeNumber: Integer; public constructor Create(aSomeNumber: Integer); virtual; function Copy: tSomeClass; procedure Whoami; end; tSomeClass2=Class(tSomeClass) End; tSomeClass3=Class(tSomeClass2) End; function tSomeClass.Copy: tSomeClass; var ctype: SomeClassType; begin ctype := SomeClassType(self.ClassType); result := ctype.Create(SomeNumber+1); end; constructor tSomeClass.Create(aSomeNumber: Integer); begin inherited Create; SomeNumber := aSomeNumber; end; procedure tSomeClass.Whoami; begin OutputDebugString(pchar( format('Class name = %s, number is %d',[self.classname,somenumber] ))); end; procedure TForm1.Button2Click(Sender: TObject); begin tSomeclass3.Create(1).Copy.Copy.Copy.Whoami; //yes, this test leaks some memory. end;
  24. Hello all, I'm using Delphi 12 enterprise and in this version I'm unable to create regions using the IDE context menu because the menu item surround is grayed out. What could have caused it and how can I re-enable it?
  25. A.M. Hoornweg

    Delphi 12 IDE, auto-formatter mutilates generics

    Eh what, the internal IDE source code formatter is deprecated? Are they just abandoning it without any replacement? I find it rather essential.
×