【问题标题】:Large common blocks with address sanitizer in 32-bit mode在 32 位模式下具有地址清理程序的大型公共块
【发布时间】:2016-07-14 03:23:20
【问题描述】:

我在使用可以简化为此示例的旧 Fortran 代码时遇到问题:

program main
implicit none
write(6,*) 'Hello!'
end program main

subroutine bigdata()
implicit none
!real*8 AA(50292712)
real*8 AA(50292713)
common /big_common/ AA
end subroutine

请注意,从不从程序中调用子例程。在 64 位机器上编译和运行它,给了我:

$ gfortran -fsanitize=address main.f ; ./a.out
 Hello!

$ gfortran -m32 main.f ; ./a.out
 Hello!

$ gfortran -m32 -fsanitize=address main.f ; ./a.out                                                                                                               
==32656== Shadow memory range interleaves with an existing memory mapping. ASan cannot proceed correctly. ABORTING.
==32656== Process memory map follows:
        0x08048000-0x08049000   /home/username/a.out
        0x08049000-0x0804a000   /home/username/a.out
        0x0804a000-0x0804b000   /home/username/a.out
        0x0804b000-0x1ffff000
        0xf5d77000-0xf5d78000
        0xf5d78000-0xf5dbc000   /lib/i386-linux-gnu/libm-2.19.so
        0xf5dbc000-0xf5dbd000   /lib/i386-linux-gnu/libm-2.19.so
        0xf5dbd000-0xf5dbe000   /lib/i386-linux-gnu/libm-2.19.so
        0xf5dbe000-0xf5dbf000
        0xf5dbf000-0xf5e38000   /usr/lib32/libquadmath.so.0.0.0
        0xf5e38000-0xf5e39000   /usr/lib32/libquadmath.so.0.0.0
        0xf5e39000-0xf5e3a000   /usr/lib32/libquadmath.so.0.0.0
        0xf5e3a000-0xf5e56000   /lib/i386-linux-gnu/libgcc_s.so.1
        0xf5e56000-0xf5e57000   /lib/i386-linux-gnu/libgcc_s.so.1
        0xf5e57000-0xf5e5a000   /lib/i386-linux-gnu/libdl-2.19.so
        0xf5e5a000-0xf5e5b000   /lib/i386-linux-gnu/libdl-2.19.so
        0xf5e5b000-0xf5e5c000   /lib/i386-linux-gnu/libdl-2.19.so
        0xf5e5c000-0xf5e74000   /lib/i386-linux-gnu/libpthread-2.19.so
        0xf5e74000-0xf5e75000   /lib/i386-linux-gnu/libpthread-2.19.so
        0xf5e75000-0xf5e76000   /lib/i386-linux-gnu/libpthread-2.19.so
        0xf5e76000-0xf5e78000
        0xf5e78000-0xf6020000   /lib/i386-linux-gnu/libc-2.19.so
        0xf6020000-0xf6022000   /lib/i386-linux-gnu/libc-2.19.so
        0xf6022000-0xf6023000   /lib/i386-linux-gnu/libc-2.19.so
        0xf6023000-0xf6027000
        0xf6027000-0xf6123000   /usr/lib32/libgfortran.so.3.0.0
        0xf6123000-0xf6124000   /usr/lib32/libgfortran.so.3.0.0
        0xf6124000-0xf6125000   /usr/lib32/libgfortran.so.3.0.0
        0xf6125000-0xf6151000   /usr/lib32/libasan.so.0.0.0
        0xf6151000-0xf6152000   /usr/lib32/libasan.so.0.0.0
        0xf6152000-0xf6153000   /usr/lib32/libasan.so.0.0.0
        0xf6153000-0xf7705000
        0xf7731000-0xf773b000
        0xf773b000-0xf773c000   [vdso]
        0xf773c000-0xf775c000   /lib/i386-linux-gnu/ld-2.19.so
        0xf775c000-0xf775d000   /lib/i386-linux-gnu/ld-2.19.so
        0xf775d000-0xf775e000   /lib/i386-linux-gnu/ld-2.19.so
        0xff80a000-0xff82c000   [stack]
==32656== End of process memory map.

gfortran 版本:

$ gfortran -v
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.1)

AA 的大小减少1(在我的测试中)可以解决这个问题。在不同的系统或情况下,限制大小可能会有所不同。

据我所知,公共块的大小远不及 2GB,我预计 -m32 会出现问题。这是地址清理程序的限制吗?我可以使用任何命令行或运行时技巧来解决此问题吗?

编辑:它可能与公共块无关,但与公共块中的数组即使从未使用过也已分配的事实有关。这会导致同样的问题:

      program main
      implicit none
*     real*8, allocatable :: AA(:)
*     !allocate(AA(378272768))
*     allocate(AA(378272769))
      !real*8 AA(50292702)
      real*8 AA(50292705)
      AA(1)=1.0d0
      write(6,*) 'Hello!'
      end program main

请注意,可分配数组的限制几乎是静态数组的 8 倍。

【问题讨论】:

  • 看看stackoverflow.com/questions/19781713/… 。旧系统是 32 位还是 36/48/60 位?
  • @cup 代码工作似乎在 32 位和 64 位系统中工作(尽管它没有经过太多测试)。据我所知,它是为 32 位或 64 位编写的。只有在添加 32 位地址清理程序时才会出现问题。

标签: gcc fortran gfortran 32-bit address-sanitizer


【解决方案1】:

这是地址清理程序的限制吗?

确实,在 32 位 Linux 上,Asan 需要 0x1ffff000-0x37ffffff 的空闲区域作为它的影子内存(请参阅 source code 了解其他平台范围)。这可能与您程序中的大型公共数组冲突。

我可以使用任何命令行或运行时技巧来解决此问题吗?

不幸的是,该地址在编译器和运行时库中被硬编码(出于性能原因),因此我不确定您是否可以在不更改代码的情况下解决此问题(例如,通过动态分配数组?)。或者您可以坚持使用 64 位版本的代码进行 Asan 测试(那里发生冲突的可能性要低得多)。

附带说明 - 建议不要将通用数组与 Asan 一起使用(请参阅 FAQ),因为这会阻止检测到其中的缓冲区溢出(不要问)。您可以使用 -fno-common 禁用它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 2021-01-26
    相关资源
    最近更新 更多