You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Ruby Nokogiri Gem正确启用Address Sanitizer

正确为Ruby及Nokogiri Gem启用Address Sanitizer的方法

我来帮你梳理一套能解决问题的完整流程——你之前遇到的符号未定义、ASan加载顺序错误,核心原因是Ruby、libxml2、libxslt、Nokogiri这几个组件必须用完全一致的ASan编译参数构建,不能只给其中一部分加ASan。下面是分步操作:


第一步:编译带ASan的Ruby

首先得让Ruby本身链接ASan运行时,不然后续扩展加载时肯定会出问题。这里以Ruby 2.5.0为例(你可以换成自己需要的版本):

# 进入Ruby源码目录
cd ruby-2.5.0
# 配置编译参数:禁用共享库避免冲突,用clang编译(ASan对clang支持更好)
./configure --disable-shared \
  CFLAGS="-fsanitize=address,undefined -ggdb -O0" \
  CXXFLAGS="-fsanitize=address,undefined -ggdb -O0" \
  LDFLAGS="-fsanitize=address,undefined" \
  CC=clang CXX=clang++
# 编译安装,-j$(nproc)是用满CPU核心加速
make -j$(nproc)
sudo make install

小贴士:加-O0是为了关闭优化,让ASan的错误报告更准确;--disable-shared能避免动态链接带来的ASan版本冲突问题。

第二步:编译带ASan的libxml2和libxslt

这两个库必须和Ruby用一样的ASan参数,而且最好安装到独立路径,别覆盖系统默认库:

编译libxml2

cd libxml2-2.9.3
./configure \
  --prefix=/usr/local/asan-libs \  # 指定独立安装路径
  CFLAGS="-fsanitize=address,undefined -ggdb -O0 -Wformat -Werror=format-security -Werror=array-bounds" \
  CXXFLAGS="-fsanitize=address,undefined -ggdb -O0 -Wformat -Werror=format-security -Werror=array-bounds" \
  LDFLAGS="-fsanitize=address,undefined" \
  CC=clang CXX=clang++
make -j$(nproc)
sudo make install

编译libxslt

cd libxslt-1.1.28
./configure \
  --prefix=/usr/local/asan-libs \
  --with-libxml-prefix=/usr/local/asan-libs \  # 依赖我们刚编译的带ASan的libxml2
  CFLAGS="-fsanitize=address,undefined -ggdb -O0" \
  CXXFLAGS="-fsanitize=address,undefined -ggdb -O0" \
  LDFLAGS="-fsanitize=address,undefined" \
  CC=clang CXX=clang++
make -j$(nproc)
sudo make install

第三步:安装带ASan的Nokogiri

现在用刚编译好的Ruby来装Nokogiri,指定用我们自己编译的带ASan的库:

# 确保用的是刚装的Ruby的gem命令,可先用which gem确认路径是/usr/local/bin/gem
gem install nokogiri --version 1.8.0 \
  -- --use-system-libraries \
  --with-xml2-include=/usr/local/asan-libs/include/libxml2 \
  --with-xml2-lib=/usr/local/asan-libs/lib \
  --with-xslt-include=/usr/local/asan-libs/include \
  --with-xslt-lib=/usr/local/asan-libs/lib \
  --with-cflags="-fsanitize=address,undefined -ggdb -O0" \
  --with-ldflags="-fsanitize=address,undefined"

注意:这里不用手动加-lasan或-lubsan,-fsanitize=address,undefined会自动帮你链接对应的运行时库。

第四步:运行脚本验证

直接用刚编译的Ruby运行脚本就行,不需要手动设LD_PRELOAD(因为Ruby已经自带ASan运行时了):

# 如果你的ASan库路径没在系统默认搜索里,先加一下
export LD_LIBRARY_PATH=/usr/local/asan-libs/lib:$LD_LIBRARY_PATH
# 运行脚本
/usr/local/bin/ruby script.rb

如果一切正常,ASan会在检测到内存泄漏、越界等问题时输出详细报告。


针对你遇到的问题的额外说明

  1. ASan runtime does not come first in initial library list:这是因为你之前用的是系统Ruby(没链接ASan),预加载ASan会导致加载顺序混乱。解决方法就是用自己编译的带ASan的Ruby,从根源避免这个问题。
  2. undefined symbol: __asan_init:这个是因为有的组件(比如Ruby、libxml2或Nokogiri)没加ASan编译,导致符号不匹配。必须确保所有相关组件都用同样的ASan参数编译。
  3. 编译Ruby时ASan报内存泄漏:旧版本Ruby本身可能存在一些已知的内存泄漏,这是正常的,只要Ruby能编译完成就不用管,我们的目标是用ASan检测Nokogiri的问题。

内容的提问来源于stack exchange,提问作者dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:33:52