背景:我正在开发一个使用 Rcpp 并包含一些 C++ 文件的包。我想用 ASAN 分析我的代码。我正在努力构建我的包。
到目前为止我做了什么
https://hub.docker.com/r/rocker/r-devel-san
docker 容器,该容器附带预构建的 R(或 RD)来与 ASAN 配合使用。-fsanitize=address
标志的 C++ 脚本以获得有意义的 ASAN 输出。src/Makevars
文件如下所示(并非所有标志都与此问题相关):CC = gcc -fsanitize=address -fno-omit-frame-pointer
CXX = g++
LDFLAGS = -fsanitize=address
PKG_CXXFLAGS = -fsanitize=address -fno-omit-frame-pointer -fno-sanitize-address-use-after-scope -D_GCL_RHACK_ -DGC_NO_MUTEX -m64 -ldl -lpthread -Wall -pipe -pedantic -Wno-unused -DNDEBUG -g -std=c++17
PKG_CFLAGS = -fsanitize=address -D_GCL_RHACK_ -fno-sanitize-address-use-after-scope
foo
):RD CMD build foo
RD CMD install -l temp_lib/ foo_1.0.tar.gz
安装命令抛出以下错误(以及构建的最后一行)
-g -O2 -c loadpathutil.c -o loadpathutil.o
g++ -fsanitize=undefined,bounds-strict -fno-omit-frame-pointer -std=gnu++17 -shared -L/usr/local/lib/R/lib -L/usr/local/lib -o foo.so RcppExports.o Read.o Utilities.o Write.o gdxcc.o loadpathutil.o -L/usr/local/lib/R/lib -lR
** R
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
Error: package or namespace load failed for ‘foo’ in dyn.load(file, DLLpath = DLLpath, ...):
installing to /work/temp_lib/00LOCK-foo/00new/foo/libs
unable to load shared object '/work/temp_lib/00LOCK-foo/00new/foo/libs/foo.so':
/work/temp_lib/00LOCK-foo/00new/foo/libs/foo.so: undefined symbol: __asan_option_detect_stack_use_after_return
我知道最终的包共享对象必须以某种方式链接到ASAN,但建议的解决方案
LDFLAGS
,PKG_LDFLAGS
似乎没有帮助。
这是我为自己编写并自己使用的文档。
clang
。 apt-get install clang
应该完成这项工作config.site
并在末尾添加以下内容## clang-ASAN, clang-UBSAN:
CC="clang -fsanitize=address,undefined -fno-sanitize=float-divide-by-zero -fno-sanitize=alignment -fno-omit-frame-pointer"
CXX="clang++ -fsanitize=address,undefined -fno-sanitize=float-divide-by-zero -fno-sanitize=alignment -fno-omit-frame-pointer -frtti"
CFLAGS="-g -O3 -Wall -pedantic"
FFLAGS="-g -O2 -mtune=native"
CXXFLAGS="-g -O3 -Wall -pedantic"
MAIN_LD="clang++ -fsanitize=undefined,address"
export ASAN_OPTIONS='detect_leaks=0:detect_odr_violation=0'
export UBSAN_OPTIONS='print_stacktrace=1'
export RGL_USE_NULL="true"
export R_DONT_USE_TK="true"
./configure \
--prefix=/opt/R/${R_VERSION} \
--enable-memory-profiling \
--enable-R-shlib \
--with-blas \
--with-lapack
make
然后我们可以通过在
bin/R
中运行R并使用包sanitizers
触发错误来检查它是否真的有效。
install.packages("sanitizers")
sanitizers::stackAddressSanitize(42)
sanitizers::heapAddressSanitize(10)