Linking fails : relocation truncated to fit: R_X86_程序占用内存大于2GB所导致的问题

来源:互联网 发布:java设计模式应用场景 编辑:程序博客网 时间:2024/05/17 07:16
  
1
 

Problem(Abstract)

This technote explains how to resolve a Purify engine: Error: The linker returned error code: 1 error, that can occur when using IBM Rational PurifyPlus.

Symptom

The following error when linking an application with PurifyPlus:


    relocation truncated to fit: R_X86_64_PC32 _P_W_8B_C
    Purify engine: Error: The linker returned error code: 1


Cause

By default, gcc generates code for the small code model. This means that the program and its symbols must be linked in the lower 2 GB of address space. You receive this error because your application is exceeding the 2 GB limit when linked with PurifyPlus.

Resolving the problem

To resolve this problem, you can do one of the following:

  1. Use the medium code model. This is done by specifying the gcc option -mcmodel=medium. In the medium code model, the program is linked in the lower 2 GB of address space, but symbols can be located anywhere in the address space (i.e. they can be located beyond 2 GB). The medium code model cannot be used in conjunction with the -fPIC compiler option.
  2. Dynamically link with the library referenced in the "relocation truncated to fit ..." message, rather than statically linking with that library.


http://www-01.ibm.com/support/docview.wss?uid=swg21413829
 
程序占用内存大于2GB所导致的问题(http://hi.baidu.com/ialen/blog/item/437d4f7fd3a7ec2f0cd7dacb.html)
2011-05-15 20:18

最近遇到了一个问题,他的程序在分配小数组的时候编译、运行都安然无恙,而一旦数组足够大之后编译就会出现含有
relocation truncated to fit
这种字样的错误信息。最后W和S同学一起调研发现是程序占用内存大于2GB所导致的问题。现在的程序的内存都大于2GB了,不得不感叹下新生代的力量。发现了问题要解决却不容易。不过在S同学的辛苦调研和亲身调试下,问题最终得以解决。偶顺手把解决方法拿了过来,万一哪天我的程序也这么变态了…
主要的参考文献是这两篇:

http://software.intel.com/en-us/articles/avoiding-relocation-errors-when-building-applications-with-large-global-or-static-data-on-intel64/
http://www.ualberta.ca/CNS/RESEARCH/LinuxClusters/64-bit.html

为防止以后网址失效,将第二篇的主要内容copy在这里:
The Portland Group, Intel, and GNU compilers installed on the AICT Linux Cluster are configured to produce 64-bit executables by default. Additional compiler flags such as the GNU -m64 are unnecessary for this purpose.
New or existing programs that use less than 2GB of memory will probably not require any modifications to their source code or to the way they are compiled. A large-memory program, on the other hand, in addition to the data size issues mentioned above, may need additional compiler flags, depending on the compiler used and how data is implemented.
Typically, large data objects are declared as either static global arrays or dynamically allocated memory. These are associated with the data and heapmemory segments, respectively. Large heap (and stack) segments do not need any special attention. However, if the size of the data segment (sum of all static global arrays) exceeds 2GB, use the appropriate flags from the following two tables.
C/C++ compilers flag
Portland pgcc -mcmodel=medium
pgCC -mcmodel=medium
Intel icc –
GNU gcc –
g++ –
Table 1 C/C++ compiler flags for accommodating large data segments.

Fortran compilers flag
Portland pgf77 -mcmodel=medium
pg90/pg95 -mcmodel=medium [-i8]¹
Intel ifort -mcmodel=medium -i-dynamic² [-i8]¹
GNU g77 -mcmodel=medium
¹ Makes intrinsic array enquiry functions return INTEGER*8 values.
² Add $INTEL_LIB_PATH to LD_LIBRARY_PATH.
Table 2 Fortran compiler flags for accommodating large data segments.
The -mcmodel flag selects the memory model or memory access modes for a program. Three memory models are supported by the compilers: small(text+data<2GB), medium (text<2GB, data>2GB), and large (text>2GB, data>2GB). Memory segments less than 2GB can be accessed with direct references, while larger segments require indirect or relative references.
Because its addressing modes are more efficient, the small model is faster than the medium model. Therefore, unless your program needs support for large data, it is best to use the small model. Text segments larger than 2GB are rare, so the large model can be ignored, and in any case, it is available only with the Intel compiler.
The default memory model for the Portland compilers is small. On the other hand, the default for both the Intel and GNU C/C++ compilers is medium, and for the Fortran compilers it is small.

If you build your program by compiling and linking in separate stages, be sure to include the -mcmodel flag (if used) on the linker command line as well.
When using -mcmodel=medium with the Intel Fortran compiler, the additional -i-dynamic flag is required to link the appropriate libraries. Because these libraries are dynamically linked, your executable must be made aware of their location. One way to do this is to amend the environment variableLD_LIBRARY_PATH with the value of INTEL_LIB_PATH as follows (bash syntax shown).
export LD_LIBRARY_PATH=$INTEL_LIB_PATH:$LD_LIBRARY_PATH
This command will also be necessary in batch job scripts. Another way is to embed $INTEL_LIB_PATH directly into the executable file using a compiler (linker) flag. For example,
ifort -mcmodel=medium -i-dynamic -i8 source.f90  -Wl,-rpath,$INTEL_LIB_PATH
The -i8 flag should be used for Fortran 90/95 code that calls any instrinsic array enquiry functions, such as SIZE. Without it, the return values of these functions are truncated to 32 bits. This is true for both Portland and Intel compilers.
对于W同学的f77程序,我们的最终解决方法是在编译和链接时都加上如下Flags:
-mcmodel=medium -i-dynamic
最后还有个补充问题。如果要用mkl库,我们发现用如下的链接方式

FLIBS +=-lmkl_lapack -lmkl_em64t -lmkl_solver -lguide -lpthread
时会出错。需要改成
FLIBS += -lmkl_intel_lp64 -lmkl_core -lmkl_sequential
同时在LD_LIBRARY_PATH环境变量中要加上intel的mkl下的lib/em64t目录所在的路径,比如
export

原创粉丝点击