问题标签 [eglibc]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 诊断神秘的 valgrind “无效写入”
[这是冗长而充满细节的。我的具体问题由下面的粗体字问题介绍。]
概括
我们在 valgrind 下运行我们的一些测试套件,遇到了一个对我来说没有多大意义的错误。我正在寻找有关更详细地找出可能出了什么问题的建议。
- Valgrind 抱怨“大小为 8 的无效写入”。
- 该错误在每次运行中都是一致的,但随着应该不相关的代码更改、不同的编译器/stdlib 版本等的出现而出现。
- 写入的地址在堆栈上,据我所知,这是我们的代码要写入的完全合理的地址。
- 它的对齐方式与写入的大小一致。
- 它发生的地方在标准库的深处。
所有这些听起来都好像真正的问题在其他地方:某些东西正在被破坏并导致后来的混乱。但这是 valgrind 报告的第一个问题,所以如果其他地方存在内存踩踏,那么 valgrind 将无法捕捉到它。我怀疑要么我遗漏了一些明显的东西,要么存在一个微妙的问题,那些比我拥有更多 valgrind 专业知识的人可能能够指出我。
一些细节
以下是一些细节和一些具体问题。
这是在 x64 硬件上运行 Ubuntu 14.04 的 Linux 机器上。
这是 valgrind 在一个相当典型的例子中的抱怨:
以“CRV”开头的东西是我们的;它们上面的东西在 libstdc++ 和 glibc 中。Ubuntu 14.04 使用 2.19 版的 glibc——除了事实上它似乎使用的是 eglibc 2.19 而不是普通的 glibc 2.19;您可以在此处找到相关版本的 printf_fp.c 。
运行 valgrind--vgdb
并要求 gdb 进行反汇编声明(与上面链接的源代码一致)当 valgrind 停止我们时我们实际上将要执行的指令是callq __mpn_lshift
.
涉及“我们的”代码的最顶层堆栈帧如下所示:
问题就在里面oss << value;
。m_valueTree
是一个std::string
;你可以猜出什么样的事情addIndent
和addElementBegin
做什么;后者使用 stringstream 来做到这一点,前者没有。(可能不相关的注释:您可能认为这看起来效率低下,您是对的,但这根本不是性能关键代码。)
所以,无论如何,我们在一条callq
指令的地址 0xffeffde68 处得到一个大小为 8 的无效写入。您希望callq
写入 指向的内存rsp
,所以它确实如此(我已经验证此时rsp
等于 0xffeffde68)......但是 valgrind 反对这一点,我不清楚为什么。
(一个明显的猜测可能是我们的堆栈溢出了。但是(1)我认为这会发生在一个看起来更圆的地址上,并且(2)我试图增加堆栈大小但它没有使这些 valgrind 抱怨消失了,并且 (3) 我预计堆栈溢出时会出现段错误,但这并没有发生,并且 (4) 我们此时并没有使用太多堆栈;最早我已经能够探测到,rsp
是 0xfff000598,所以我们在故障点使用了不到 10k 的堆栈。)
问题:我是否应该清楚valgrind反对这篇文章的内容?如果没有,有没有办法让 valgrind 告诉我更多关于它为什么不喜欢它的信息?
问题:这里的直接问题是 valgrind 中的错误是否合理(尽管可能是由我们代码中的一些早期不当行为引起的)?如果是这样,有什么好的方法可以追踪或排除这些事情吗?
问题:这看起来像 glibc 或 libstdc++ 的任何已知问题吗?(到目前为止,我所做的此类网络搜索尚未发现任何此类已知问题。)
如果有用,请提供更多信息
如果我允许在此无效写入后继续执行,则 valgrind 会在__mpn_lshift
此处调用的函数内部抱怨大小为 8 的无效读取。它从同一地址读取并在 gdb 中反汇编毫不奇怪地表明它retq
是那__mpn_lshift
是罪魁祸首。
我的堆栈框架似乎都不是很大。Valgrind 不会抱怨大堆栈帧,询问堆栈是否移动,建议增加--max-stacksize
,或任何类似的东西。
在另一台具有稍微不同版本的 gcc 和可能不同版本的标准库的机器上,valgrind 再次报告大小为 8 的无效写入,__printf_fp
但在它的不同部分,这次不是在调用指令上。(不幸的是,这是在同事的计算机上,并且由于我们观察到了这一点,因此进行了一些更改,使他的版本显示出与我相同的失败,因此我无法自信地提供更多详细信息。但我是 95%确保失败发生在一条mov
指令上,并且严格写在当前堆栈帧内。)
malloc - `malloc_info` 输出中的字段是什么意思?
我正在调用malloc_info(3)
并获取 XML 输出。
我在网上找到的所有内容都表明“这可能会发生变化,我们不会费心记录它”。
但这对于调查潜在内存碎片问题的人来说并不是非常有用。
以下是一些片段:
等等等等,直到……
这一切究竟意味着什么?
我会将我自己的一些笔记/想法放在答案中,但如果有人比我了解更多,我将不胜感激。
ldd --version
报告Ubuntu EGLIBC 2.19-0ubuntu6.13
,这是我对 glibc 版本的最佳猜测。
yocto - 如何将 ldd 实用程序添加到 bitbake 图像
我需要ldd
在 yocto 的最终图像中使用实用程序。当我usbutils
之前需要时,我继续在 ../build/conf/local.conf 文件中添加了该行
CORE_IMAGE_EXTRA_INSTALL += "usbutils"
在四处搜索之后,我发现 ldd 是libc-bin
包的一部分,至少在我的 Ubuntu 机器上。但读完这篇文章后,我发现它在eglibs
配方中,而不是标准包装的一部分。添加类似于 usbutils 的 libc-bin 会引发Nothing RPROVIDES libc-bin
可以理解的错误。
如果我需要添加 eglibs 配方,我会采取哪些步骤将 ldd 放到我的图像上。如果没有,是否有另一种方法可以做到这一点。
请多多包涵,我还是 yocto 和 bitbake 的新手。
arm - 如何修复目标和构建机器之间的 GLIBC 版本不匹配?
我正在为嵌入式设备 (Moxa UC-8100) 交叉编译应用程序,并且遇到了 GLIBC 的版本问题。
我安装了 Debian 9(按照嵌入式设备供应商的指示)并使用 arm-linux-gnueabihf 工具链。在设备上运行我的构建时,它说
当我ldd --version
在设备上运行时,我可以看到它的版本为 2.13:
所以,问题很清楚(我的程序是用 2.16 构建的,但我有 2.13 可用),但我该如何解决这个问题?
更新我在 Debian 9 64 位 VM 上使用标准 Debian 软件包(包括一些 Moxa 软件包)安装了交叉编译工具链:
添加deb http://debian.moxa.com/debian stretch main contrib non-free
到/etc/apt/sources.list.d/moxa.sources.list
,然后: