- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am building a DLL for the first time with the IFX compiler (2025.1.1). I have built it for many years with the IFORT compiler (most recently 2021.11.0). I'm noticing a huge difference in the size of the .bss section of the DLLs produced with each compiler: IFORT is 122MB and IFX is 2.9GB!
I'm currently using Visual Studio 2022 in both instances. I tried to keep the compiler and linker settings as close to identical between the two compilers as I could. Also, optimization is turned off for my Release builds, so the .bss section is identical size between Release and Debug builds for both compilers. I'm showing results of Debug builds below. I'm working on Windows 11, everything is x64.
When build with the IFORT compiler, the top of my MAP file showing the size of the .bss section of the DLL is:
Preferred load address is 0000000180000000
Start Length Name Class
0001:00000000 0068bf90H .text CODE
0001:0068bf90 00002380H .text$mn CODE
0001:0068e310 00000040H .text$mn$00 CODE
0001:0068e350 000000ddH .text$x CODE
0002:00000000 00000428H .idata$5 DATA
0002:00000428 00000038H .00cfg DATA
0002:00000460 00000008H .CRT$XCA DATA
0002:00000468 00000008H .CRT$XCZ DATA
0002:00000470 00000008H .CRT$XIA DATA
0002:00000478 00000008H .CRT$XIZ DATA
0002:00000480 00000008H .CRT$XPA DATA
0002:00000488 00000008H .CRT$XPZ DATA
0002:00000490 00000008H .CRT$XTA DATA
0002:00000498 00000008H .CRT$XTZ DATA
0002:000004a0 00000000H .gehcont$y DATA
0002:000004a0 00000000H .gfids$y DATA
0002:000004a0 00071360H .rdata DATA
0002:00071800 00000080H .rdata$CastGuardVftablesA DATA
0002:00071880 00000080H .rdata$CastGuardVftablesC DATA
0002:00071900 0000007cH .rdata$voltmd DATA
0002:0007197c 0000031cH .rdata$zzzdbg DATA
0002:00071c98 00000008H .rtc$IAA DATA
0002:00071ca0 00000008H .rtc$IZZ DATA
0002:00071ca8 00000008H .rtc$TAA DATA
0002:00071cb0 00000008H .rtc$TZZ DATA
0002:00071cb8 0000ac48H .xdata DATA
0002:0007c900 00005b5cH .edata DATA
0002:0008245c 000000a0H .idata$2 DATA
0002:000824fc 00000014H .idata$3 DATA
0002:00082510 00000428H .idata$4 DATA
0002:00082938 00000864H .idata$6 DATA
0003:00000000 00028120H .data DATA
0003:00028120 07af39a8H .bss DATA
0004:00000000 00006f60H .pdata DATA
0005:00000000 0004db90H .trace DATA
When built with the IFX compiler, the top of my MAP file showing the size of the .bss section of the DLL is:
Preferred load address is 0000000180000000
Start Length Name Class
0001:00000000 0068b962H .text CODE
0001:0068b970 000021d3H .text$mn CODE
0001:0068db50 00000036H .text$mn$00 CODE
0001:0068db90 000000edH .text$x CODE
0002:00000000 00044af0H .rdata DATA
0002:00044b00 00000080H .rdata$CastGuardVftablesA DATA
0002:00044b80 00000080H .rdata$CastGuardVftablesC DATA
0002:00044c88 00000038H .00cfg DATA
0002:00044cc0 00000008H .CRT$XCA DATA
0002:00044cc8 00000008H .CRT$XCZ DATA
0002:00044cd0 00000008H .CRT$XIA DATA
0002:00044cd8 00000008H .CRT$XIZ DATA
0002:00044ce0 00000008H .CRT$XPA DATA
0002:00044ce8 00000008H .CRT$XPZ DATA
0002:00044cf0 00000008H .CRT$XTA DATA
0002:00044cf8 00000008H .CRT$XTZ DATA
0002:0004ba18 00000008H .rtc$IAA DATA
0002:0004ba20 00000008H .rtc$IZZ DATA
0002:0004ba28 00000008H .rtc$TAA DATA
0002:0004ba30 00000008H .rtc$TZZ DATA
0002:0004ba38 00020d24H .xdata DATA
0003:00000000 00026b84H .data DATA
0003:00026b84 b7176d94H .bss DATA
0004:00000000 0001d8a4H .pdata DATA
0005:00000000 00000018H .retplne DATA
0006:00000000 000dadbaH .trace DATA
Granted my code features some common blocks, use of /Qsave and /Qinit:zero (see compiler settings below), but still, is it expected that there's such a big difference in the output of the compilers using the same code and same compiler settings?
Currently I am having trouble using the DLL built by the IFX compiler with P/Invoke (from C#), which I'm thinking is due to this size exceeding some limitation. I'd appreciate any insight that could help. Do I need to drastically re-vamp and re-test my code (it's old), or is there a compiler/linker setting that can restore similar output.
Thanks,
Tom.
Debug compiler and linker settings for IFORT and IFX:
/nologo /debug:full /Od /assume:buffered_io /fpp /assume:nocc_omp /reentrancy:threaded /extend-source:132 /warn:none /Qsave /assume:byterecl /Qinit:zero /fpe:1 /names:uppercase /iface:stdref /iface:mixed_str_len_arg /module:"xxxx" /object:"xxxx" /traceback /libs:dll /threads /dbglibs /4Yportlib /c
/OUT:"xxxx.dll" /INCREMENTAL:NO /NOLOGO /LIBPATH:"..\bin\Debug\x64" /MANIFEST /MANIFESTFILE:"xxxx.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"xxxx.pdb" /MAP /MAPINFO:EXPORTS /SUBSYSTEM:WINDOWS /STACK:18000000,8000000 /LARGEADDRESSAWARE /IMPLIB:"xxxx.lib" /DLL
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have also encountered problems with the size of a DLL when migrating from ifort to ifx:
Do you have the same behaviour?
So far I haven't found a solution to this problem. Except keeping old good ifort for this specific code...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Marc,
Thanks for pointing out your thread. Indeed, my observation seems related to yours. In my case, the extra size is clearly in the BSS section of my DLL, i.e. the uninitialized variables section. While I'll concede the code may not be the most modern style, which I'm sure is leading to more static memory use than otherwise, I'm more interested in why such a big difference between IFORT and IFX (128MB vs. 2.9GB).
Since my post today, I've tried a couple things:
- compile with /O1 - didn't make a significant difference
- compile with /heap-arrays:100 - didn't make any difference at all
I'm hoping that someone with some deeper knowledge of the IFX compiler will know why it is creating the BSS section so much larger than IFORT.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have spent more time analyzing the linker MAP file for the DLL created by the IFX compiler (the one with the .BSS section nearly 3GB in size). I now think the size of the .BSS section is directly related to the number of files in my project that include a given file containing common blocks.
A bunch of files in my project (25 exactly) contain one or more subroutines which include the line:
include 'DATABASE.CMN'
The DATABASE.CMN file contains a bunch of variable definitions and common blocks.
When I look carefully at the symbol offsets in the linker MAP file (which are thankfully sorted by obj file), I can see at the transition from the last variable in a file that contains DATABASE.CMN to the first variable in another file increments the offset by approximately 122MB. For example, in the following snippet where the variables transition from File1.obj to File2.obj, the offsets jump from 00026bb8 to 07516d40 (122,618,248 bytes). In this case, File1.obj has subroutines that include DATABASE.CMN (multiple such subroutines).
...
0003:00026bb0 SUBR1$IEND 0000000180723bb0 File1.obj
0003:00026bb4 SUBR1$IST 0000000180723bb4 File1.obj
0003:00026bb8 SUBR1$I 0000000180723bb8 File1.obj
0003:07516d40 SUBR2$IVAL2 0000000187c13d40 File2.obj
0003:07516d44 SUBR2$IVAL1 0000000187c13d44 File2.obj
0003:07516d48 SUBR2$ILEN 0000000187c13d48 File2.obj
...
Conversely, when transitioning from files that do not contain subroutines that include DATABASE.CMN, there is no corresponding large jump in the symbol offsets.
As I mentioned, there are 25 files in the project with one or more subroutines that include DATABASE.CMN. In each case the offset when going from one of these files to the next jumps by ~122MB. So, 122MB * 25 = ~3GB, which is what my overall BSS section length is (B7176D94 == 3,071,765,908).
Therefore, I have to conclude that each file (not subroutine) that includes DATABASE.CMN, is adding a copy of the static variables and common blocks that are defined in DATABASE.CMN into the BSS section.
Does this make sense? Again, this didn't seem to be the case with the old compiler.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am checking with the team on this one. I would guess it's this option:
/Qinit:zero
we have a couple of efforts underway similar to initializations. Also another similar issue with .data section size but it's a heavily OO example with CLASS object arguments. It sounds like your example is using COMMONs which would indicate it's probably older legacy F77 era code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Ron,
Thanks for looking into this, and I look forward to hearing if the team has any comments. You are right, the code for my DLL has been around for many years and it is in an older style for the most part. But it is well-tested, so I'm hoping to find a solution that doesn't involve a major re-factor.
Just now I tried toggling some more of the compiler options, including:
- turn off /Qinit:zero - no change whatsoever in BSS section size
- change /Qsave to "Default Local Storage" - tiny change in BSS section size but still over 3GB
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Update: I have overcome the problem by refactoring my code. I still think there is something strange happening with the IFX compiler in this scenario, but for the time being I have a workaround. I'll explain below.
As I suspected yesterday, the static variable declarations and COMMON blocks defined in the DATABASE.CMN file were involved. That file declared dozens of variables and arrays and put them into a number of COMMON blocks so they could be shared between subroutines comprising the DLL. Any subroutine that needed to use those variables had a line:
INCLUDE 'DATABASE.CMN'
What I did was change the DATABASE.CMN file into a MODULE (basically wrap the MODULE/END MODULE keywords around the variable declarations and remove the COMMON block statements). Then I changed all instances of:
INCLUDE 'DATABASE.CMN'
to
USE DATABASE_CMN
Once I did that and rebuilt the DLL, the MAP file shows:
Preferred load address is 0000000180000000
Start Length Name Class
0001:00000000 0068a4e2H .text CODE
0001:0068a4f0 000021d3H .text$mn CODE
0001:0068c6d0 00000036H .text$mn$00 CODE
0001:0068c710 000000edH .text$x CODE
0002:00000000 00044ad0H .rdata DATA
0002:00044b00 00000080H .rdata$CastGuardVftablesA DATA
0002:00044b80 00000080H .rdata$CastGuardVftablesC DATA
0002:00044c88 00000038H .00cfg DATA
0002:00044cc0 00000008H .CRT$XCA DATA
0002:00044cc8 00000008H .CRT$XCZ DATA
0002:00044cd0 00000008H .CRT$XIA DATA
0002:00044cd8 00000008H .CRT$XIZ DATA
0002:00044ce0 00000008H .CRT$XPA DATA
0002:00044ce8 00000008H .CRT$XPZ DATA
0002:00044cf0 00000008H .CRT$XTA DATA
0002:00044cf8 00000008H .CRT$XTZ DATA
0002:0004ba18 00000008H .rtc$IAA DATA
0002:0004ba20 00000008H .rtc$IZZ DATA
0002:0004ba28 00000008H .rtc$TAA DATA
0002:0004ba30 00000008H .rtc$TZZ DATA
0002:0004ba38 00020d34H .xdata DATA
0003:00000000 000269c4H .data DATA
0003:000269c4 07af26f4H .bss DATA
0004:00000000 0001d8b0H .pdata DATA
0005:00000000 00000018H .retplne DATA
0006:00000000 000da36bH .trace DATA
The BSS section is now ~129MB bytes instead of ~3GB, and it can be called fine through P/Invoke.
Hopefully that makes sense. I still think there's something with IFX repeating the variable declarations in the BSS section any time DATABASE.CMN was included in a source file. It seems to me it was not properly recognizing that the variables were shared
through COMMON blocks. FORTRAN is not my mother tongue, though, so I'd be interested to hear other's thoughts on this hypothesis.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Did you initialize the COMMONs in that include file? If so, move the initializations to a BLOCK DATA subprogram - it is a standards violation to initialize a COMMON variable in more than one program unit, but in many cases you can get away with it. Your module solution works too, though you don't even need COMMON anymore once you have the variables in a module.
A caveat regarding BLOCK DATA - ifx has, I think still, a bug in that a BLOCK DATA subprogram won't be linked in from a library even if there is an EXTERNAL declaration for it. If you're not using a static library as part of your build it doesn't matter, but otherwise you would need to explicitly name the object file containing the BLOCK DATA in the linker properties as Additional Dependencies.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page