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

multiple definition link error when using contained subroutines

Chris_Payne
Beginner
2,674 Views
[bash]       program m
call s1()
call s2()
end

subroutine s1() implicit none integer*4 i integer*4 linlen(255) i = 66 call isub() contains subroutine isub() 350 format ('1',A) write (6,350) 's22 isub', i end subroutine end subroutine s2() implicit none integer*4 i integer*4 linlen(255) i = 66 call isub() contains subroutine isub() 350 format ('1',A) write (6,350) 's22 isub', i end subroutine end [/bash]

Attempting to compile and link these returns the following linker error:

/tmp/ifortfsvkDg.o: In function `vfe$0000isub$BLK':
s2.for:(.text+0xee): multiple definition of `vfe$0000isub$BLK'
/tmp/ifortfATo83.o:s1.for:(.text+0xee): first defined here

It appears to be caused by the Format statements referring to an array in the containing subroutine. If this is a compiler bug,can we get a fix in the 11.1 version? We are using 11.1.072, intel64, onRHEL5.5

Thanks
0 Kudos
10 Replies
mecej4
Honored Contributor III
2,673 Views
I have nothing to say about the linker error message, but your program has two bugs:

1. To use linlen(1) in a VFE, you must give it a value beforehand. Otherwise, the value is undefined when it is used.

2. You are using an A<..> format with an I/O list containing a string and an integer. The format, however, contains only one specification. The repeat rules kick in, and the integer is printed using a character format.
0 Kudos
Kevin_D_Intel
Employee
2,673 Views
This is not reproducing with the default compile options. Will you please show the complete compiler command line (like shown below) that causes this linker error?

Thank you.

$ ifort -V s2.for

Intel Fortran Intel 64 Compiler Professional for applications running on Intel 64, Version 11.1 Build 20100414 Package ID: l_cprof_p_11.1.072
Copyright (C) 1985-2010 Intel Corporation. All rights reserved.

Intel Fortran 11.1-2739
GNU ld version 2.17.50.0.6-5.el5 20061020
$

0 Kudos
mecej4
Honored Contributor III
2,673 Views
To reproduce the bug, which is present in the current 12.0 version as well, the source must be split such that subroutines S1 and S2 are in separate files. The OP did not make this clear.
0 Kudos
Kevin_D_Intel
Employee
2,674 Views
Ah, yes. I overlooked the s1.for there. Thank you, mecej4. I will ask for Development's thoughts.
0 Kudos
Kevin_D_Intel
Employee
2,673 Views

I dug a bit deeper and found the compiler declares the VFE function, vfe$0000isub$BLK, as global.

$ readelf -s s2.o | grep vfe

14: 0000000000000100 16 FUNC GLOBAL DEFAULT 2 vfe$0000isub$BLK

When declared local (modify ASM to remove the .globl directive), the program links and executes correctly. I verified s1 and s2 call their own isub() with some minor unique changes to the printed string.

I sent this Development (internal tracking id below) asking whether the internally generated VFE function is correctly declared as global or not.

(Internal tracking id: DPD200163600)

(Resolution Update on 02/21/2011): This defect is fixed in the Intel Fortran Composer XE 2011 Update 2 (2011.2.137 - Linux)

0 Kudos
mecej4
Honored Contributor III
2,673 Views
Kevin, following up on what you wrote, I looked at the ASM code for function vfe$0000ISUB$BLK. It is just a helper function, which dereferences %eax twice and returns the result in %eax. What it does is independent of the specific VFE expression which causes this function code to be emitted.

If the code in the function is always the same, only one copy is needed instead of many local copies. All that has to be done is to tell the linker to ignore multiple occurrences, as with COMMON blocks.

Therefore, the linker flags /FORCE:multiple (Windows) and -z muldefs (Linux) should function as interim solutions. However, these flags apply to all functions, so there is a small risk of producing a bad executable when there are other user written functions of which multiple copies are given to the linker.

0 Kudos
Kevin_D_Intel
Employee
2,674 Views

Good points and good advice.

That illustrates the value and most likely intent in declaring it global. A single source file containing multiple subprograms can share a single copy.

Our ld expert said it's all or nothing with -z muldefs; there's no method to permit multiple definitions of select routines.

I'm still waiting for our Fortran developers thoughts but somewhat expect they'll share your conclusions.

0 Kudos
Kevin_D_Intel
Employee
2,674 Views
I have to backtrack on what I said. The VFE helper function name is encoded with the host routine name so that really only makes it known and usable within the host routine except for this special case where the host name is reused. That also means multiple unique named "vfe$...." functions will exist for VFE uses in other subprograms, includingwithin a single source file.

We'll see what Development has to say.
0 Kudos
Kevin_D_Intel
Employee
2,674 Views

Development agrees the VFE helper function name should be declared static (like the contained routine is in this example) and not extern. This will be addressed in future Intel Fortran Composer XE 2011 update, but it will not be addressed for the 11.1 release, sorry.

They also said the code in the function is not always the same; it varies with the expression in the VFE. They also agree the "force thelink" is a usable interim solution for this case.

0 Kudos
Kevin_D_Intel
Employee
2,674 Views
This defect is fixed in the Intel Fortran Composer XE 2011 Update 2 (2011.2.137 - Linux)
0 Kudos
Reply