Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29260 Discussions

Weird mis-initialization of C_NULL_PTR

Jugoslav_Dujic
Valued Contributor II
919 Views
I'm porting Xeffort to use ISO_C_BINDING (at last partially) and I encountered a weird problem, that I can't wrap my head around.

The problem is that C_NULL_PTR does not point to NULL, as one can see by debugging e.g. ExWinMain.f90 in the attached solution (XWizard = startup .exe project, Xeffort=static library). When I check its value, it points to #440025FF, while LOC(C_NULL_PTR) gives #442022 . When I further examine disassembly, I get:
--- No source file -------------------------------------------------------------
00442021 CC int 3
ISO_C_BINDING_mp_C_NULL_PTR:
00442022 FF 25 00 44 44 00 jmp dword ptr [__imp__ISO_C_BINDING_mp_C_NULL_PTR (444400h)]
Apparently, what I get is , rather than the . I can only conclude that either I went berzerk, or the compiler did... but I can't see what triggered it. The problem is not reproducible in simple projects.

Steve, I'd appreciate if you could take a look -- I assume you'd be curious...
0 Kudos
6 Replies
jimdempseyatthecove
Honored Contributor III
919 Views

Steve will have to comment on this for himself. What I think is going on is

IVF seems to treat PARAMETER in a similar manner as text substitution macros in C/C++

In iso_c_binding.f90 we have:

TYPE(C_PTR), PARAMETER :: C_NULL_PTR = C_PTR(0)

So my guess is with text substitution C_NULL_PTR would look like a function call C_PTR(0). Initializers would work but the contents would show the address of the funcion (or DLL dispatch table address).

Jim Dempsey

0 Kudos
Jugoslav_Dujic
Valued Contributor II
919 Views
If you mean that it's just the debugger that fools me -- unfortunately, it's not. The code misbehaves throughout, i.e. everything is consistent with the behavior I observe with the debugger.

If you mean that it's the compiler that does the "text substitution", yes, I think so too. A possible culprit is the static library where ISO_C_BINDING is first used (rather than in the main .exe), but I don't currently have the time to try to create such small sample.
0 Kudos
Steven_L_Intel1
Employee
919 Views
The problem shows up only when you link against the DLL libraries. C_NULL_PTR (and similar constants) are defined in the run-time DLL but are not declared with DLLIMPORT in the module, so the compiler does not know that it has to do an extra level of indirection to access the value. Unfortunately, the cure is not as simple as adding DLLIMPORT as that will cause a linker warning when linking statically!

We're working on a solution for this. There is no "text substitution" involved.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
919 Views
MADsblionel:
The problem shows up only when you link against the DLL libraries.

Oh I see now. I did try to change the RTL to the static one but it didn't work... just now, I see that I did that for the wrong project Smiley with tongue out [:-P]. And just now I recognize those jmp commands as artefacts of Dll import library...

However, there is no easy workaround. I can't see a way to declare another TYPE(C_PTR), PARAMETER and initialize it in a standard-conforming way (I planned to try my luck port it to gfortran/f95)... TRANSFER is not allowed in initialization expressions. Any creative ideas, anyone? smiley [:-)]
0 Kudos
Steven_L_Intel1
Employee
919 Views
Well, if you are building a DLL, you can simply make a copy of ISO_C_BINDING.f90 and add DLLIMPORT directives to those constants, and then build with this source. If you have USE,INTRINSIC you'll want to rename the .mod to be .modintr.

I wish I had a better idea.
0 Kudos
Steven_L_Intel1
Employee
919 Views
The simple workaround is to compile ISO_C_BINDING.f90 into your own project and use its object file. You can keep using the predefined .modintr file.

The fix we came up with is complicated, but the alternatives were more so! We're going to pull the object files for the intrinsic modules out of the "ifcore" library, static and DLL, and put them all in a new static library called ifmodintr.lib. The sources for the intrinsic modules will be modified to add an OBJCOMMENT directive to reference this library, which will get used for both static and dynamic linking. This is safe because the procedures and objects in the intrinsic modules are not referenced by the rest of the run-time library.

Unfortunately, we won't be able to make this change for 11.0, but it will go into our next release after that. I have added a release note on the topic. This problem also affects many named constants in the new IEEE floating point intrinsic modules - the same workaround applies.
0 Kudos
Reply