SFML项目加载字体时出现Valgrind无效内存读取错误
解决SFML字体加载导致的Valgrind无效读取错误
问题现象
以下代码在加载SFML字体时,会触发Valgrind报告两个相同的无效读取错误:
// g++ sfml.cpp -o sfml_test -lsfml-graphics -lsfml-window -lsfml-system #include <SFML/Graphics.hpp> #include <iostream> int main() { sf::Font font; if (!font.loadFromFile("font.ttf")) { std::cout << "ruh oh" << std::endl; } sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!"); return 0; }
Valgrind错误输出示例:
==7557== Invalid read of size 8 ==7557== at 0x401D734: strncmp (strcmp.S:175) ==7557== by 0x400604D: is_dst (dl-load.c:209) ==7557== by 0x4008566: _dl_dst_count (dl-load.c:246) ==7557== by 0x4008757: expand_dynamic_string_token (dl-load.c:388) ==7557== by 0x40088D1: fillin_rpath.isra.0 (dl-load.c:460) ==7557== by 0x4008BE1: decompose_rpath (dl-load.c:631) ==7557== by 0x4009745: cache_rpath (dl-load.c:673) ==7557== by 0x4009745: cache_rpath (dl-load.c:654) ==7557== by 0x4009745: _dl_map_object (dl-load.c:2074) ==7557== by 0x400DDC0: openaux (dl-deps.c:64) ==7557== by 0x4C0CACF: _dl_catch_exception (dl-error-skeleton.c:208) ==7557== by 0x400E138: _dl_map_object_deps (dl-deps.c:248) ==7557== by 0x4013DAA: dl_open_worker (dl-open.c:571) ==7557== by 0x4C0CACF: _dl_catch_exception (dl-error-skeleton.c:208) ==7557== Address 0x5a25719 is 9 bytes inside a block of size 15 alloc'd ==7557== at 0x483877F: malloc (vg_replace_malloc.c:307) ==7557== by 0x401C29A: strdup (strdup.c:42) ==7557== by 0x4008B74: decompose_rpath (dl-load.c:606) ==7557== by 0x4009745: cache_rpath (dl-load.c:673) ==7557== by 0x4009745: cache_rpath (dl-load.c:654) ==7557== by 0x4009745: _dl_map_object (dl-load.c:2074) ==7557== by 0x400DDC0: openaux (dl-deps.c:64) ==7557== by 0x4C0CACF: _dl_catch_exception (dl-error-skeleton.c:208) ==7557== by 0x400E138: _dl_map_object_deps (dl-deps.c:248) ==7557== by 0x4013DAA: dl_open_worker (dl-open.c:571) ==7557== by 0x4C0CACF: _dl_catch_exception (dl-error-skeleton.c:208) ==7557== by 0x40138F9: _dl_open (dl-open.c:837) ==7557== by 0x545C257: dlopen_doit (dlopen.c:66) ==7557== by 0x4C0CACF: _dl_catch_exception (dl-error-skeleton.c:208)
移除字体加载代码后,Valgrind不再报错。程序可正常执行,字体能成功加载使用。
环境信息
- 操作系统:PureOS 10(Debian分支)
- g++版本:(Debian 10.2.1-6) 10.2.1 20210110
- glibc版本:2.31
- SFML版本:2.5或2.6,可能通过
sudo apt-get install libsfml-dev安装
解决方法
1. 使用Valgrind抑制文件(最简单方案)
该错误源于glibc动态链接器处理rpath时的内存对齐问题,属于系统库层面的假阳性错误,不影响程序运行。可以创建抑制文件忽略这类错误:
- 创建抑制文件
glibc-rpath.supp,内容如下:
{ glibc_rpath_invalid_read Memcheck:Addr4 Memcheck:Addr8 fun:strncmp fun:is_dst fun:_dl_dst_count fun:expand_dynamic_string_token fun:fillin_rpath.isra.0 fun:decompose_rpath fun:cache_rpath fun:_dl_map_object fun:openaux fun:_dl_catch_exception fun:_dl_map_object_deps fun:dl_open_worker } { glibc_rpath_invalid_read_2 Memcheck:Addr4 Memcheck:Addr8 fun:strncmp fun:is_dst fun:_dl_dst_substitute fun:fillin_rpath.isra.0 fun:decompose_rpath fun:cache_rpath fun:_dl_map_object fun:openaux fun:_dl_catch_exception fun:_dl_map_object_deps fun:dl_open_worker }
- 运行Valgrind时指定抑制文件:
valgrind --suppress=glibc-rpath.supp ./sfml_test
2. 从源码编译静态链接的SFML
Debian仓库的SFML可能依赖动态链接的系统库,导致触发rpath问题。自行编译静态链接的SFML可避免该问题:
- 安装编译依赖:
sudo apt-get install cmake libfreetype6-dev libx11-dev libxrandr-dev libudev-dev libopenal-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev
- 下载并编译SFML(以2.6.1版本为例):
git clone https://github.com/SFML/SFML.git -b 2.6.1 cd SFML mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DSFML_STATIC_LIBRARIES=ON make -j$(nproc) sudo make install
- 编译程序时使用静态链接:
g++ sfml.cpp -o sfml_test -static -lsfml-graphics-s -lsfml-window-s -lsfml-system-s -lfreetype -lX11 -lXrandr -ludev -lopenal -lflac -lvorbis -lGL -lEGL
3. 升级glibc或Valgrind
该错误是glibc 2.31与Valgrind 3.16.1的兼容性问题,升级到更新版本的glibc(2.32+)或Valgrind(3.18+)可解决。不过PureOS 10为稳定版,升级可能需要手动编译或添加第三方源。
内容的提问来源于stack exchange,提问作者Momus
相关产品推荐
相关产品推荐

