A.M. Hoornweg 144 Posted October 13, 2020 Hello all, I have a 32-bit application written in Delphi XE that I would like to compile with the PE flag "IMAGE_FILE_LARGE_ADDRESS_AWARE", because I'm occasionally nearing the 2 GB RAM limit. I can't compile this application in 64 bit mode due to dependencies on some 32-bit DLLs. My question: in order to test and debug this in a reasonable time frame, is there any way I can quickly "provoke" any possible lurking bugs (such as pointer math that may still use signed integers somewhere)? For example, is there any way of telling the fastMM4 memory manager to start allocating heap addresses top-down instead of bottoms-up, so that all objects are allocated "above" 2GB ? Share this post Link to post
Jacek Laskowski 57 Posted October 13, 2020 https://www.thedelphigeek.com/2019/04/fastmm4-large-memory.html Share this post Link to post
A.M. Hoornweg 144 Posted October 13, 2020 22 minutes ago, Jacek Laskowski said: https://www.thedelphigeek.com/2019/04/fastmm4-large-memory.html Thank you! I am already using that version of FastMM4 with the default options (I just checked, options fulldebugmode and AlwaysAllocateTopDown are set). But when I debug my program, compiled with {$SetPEFlags $0020}, it appears that allocated objects such as my main form still have addresses way below 2 GB. Could it be that the {AlwaysAllocateTopDown} option isn't working in FastMM4 ? Share this post Link to post
Vandrovnik 214 Posted October 13, 2020 Could you just allocate some memory (1-2 GB, probably in smaller chunks), so that other allocations have to be from the top part? Share this post Link to post
Guest Posted October 13, 2020 This 2 minutes ago, Vandrovnik said: Could you just allocate some memory (1-2 GB, probably in smaller chunks), so that other allocations have to be from the top part? Or 2) Cause a memory leak and see for your self that the reported address is bigger than $8000000. 3) Call VirtualAlloc manually requesting address's above $80000000. Share this post Link to post
A.M. Hoornweg 144 Posted October 13, 2020 I've got it working now, thanks! Share this post Link to post
A.M. Hoornweg 144 Posted October 13, 2020 I have a bad feeling about this. When I perform a search (using Agent Ransack) for the string "Integer(" in the subdirectory where I keep my third-party libraries, I see lots and lots of places where pointers are being cast into signed 32-bit integers. I see this especially in old libraries originally written by TurboPower, such as Abbrevia and Async Professional. For example, the version of Abbrevia that can currently be downloaded using Getit for Delphi 10.4.1 contains the following line in unit AbCabTyp.pas (line 460): Result := Integer(TFileStream.Create(Archive.FIIPName, fmCreate)) This is just an example (my application does not use that particular unit) but these libraries are riddled with such gems. Am I neurotic if I distrust such libraries in 32-bit code compiled with the large address space awareness flag ? Share this post Link to post
Anders Melander 1784 Posted October 13, 2020 25 minutes ago, A.M. Hoornweg said: Result := Integer(TFileStream.Create(Archive.FIIPName, fmCreate)) As long as it doesn't do "pointer math" on the integer value then there shouldn't be problems casting between integer and pointer. 1 Share this post Link to post
Rollo62 536 Posted October 13, 2020 15 minutes ago, Anders Melander said: As long as it doesn't do "pointer math" on the integer value then there shouldn't be problems casting between integer and pointer. Wouldn't be the NativeInteger the right cast for a pointer ? Matching the right bitness on 32- and 64-Bit machines, to the same pointer bitness ? 1 Share this post Link to post
Vandrovnik 214 Posted October 13, 2020 16 minutes ago, Anders Melander said: As long as it doesn't do "pointer math" on the integer value then there shouldn't be problems casting between integer and pointer. This code is a problem when used in 64-bit version... Share this post Link to post
Lars Fosdal 1792 Posted October 13, 2020 IMO, the > 2Gb 32-bit trick is an errorprone kludge. We are also dependent on 32-bit DLLs - but are considering going the extra length to isolate them behind an API of some sort. Share this post Link to post
Anders Melander 1784 Posted October 13, 2020 1 minute ago, Rollo62 said: Wouldn't be the NativeInteger the right cast for a pointer ? Matching the right bitness on 32- and 64-Bit machines, to the same pointer bitness ? 2 minutes ago, Vandrovnik said: This code is a problem when used in 64-bit version... Dudes. I'm not stupid. I'm not saying that it's good practice only that it's safe to cast between pointer and integer. The OP said that this was for 32-bit only so bringing 64-bit into the equation is also irrelevant. Thanks for playing. Share this post Link to post
FPiette 383 Posted October 13, 2020 9 minutes ago, Rollo62 said: Wouldn't be the NativeInteger the right cast for a pointer ? Definitely not ! Use UIntPtr (Alias to NativeUInt) which is a type especially created for that purpose. 2 Share this post Link to post
Rollo62 536 Posted October 13, 2020 27 minutes ago, FPiette said: Definitely not ! Use UIntPtr (Alias to NativeUInt) which is a type especially created for that purpose. Yes, right. type UIntPtr = NativeUInt; Share this post Link to post