【问题标题】:Invalid write of size 1 X bytes **inside** a block of size >X **alloc'd**大小为 1 X 字节的无效写入 **在 ** 大小 >X 的块中 **alloc'd**
【发布时间】:2017-09-20 22:23:55
【问题描述】:

我在调试 valgrind 错误方面相对较新,这个让我很难过:

==1920== Invalid write of size 1
==1920==    at 0x4C2ECC7: strcpy (/builddir/build/BUILD/valgrind-3.11.0/memcheck/../shared/vg_replace_strmem.c:506)
==1920==    by 0x1D533B57: CSR_bullet (packages/tests-vg/vetr/src/cstringr.c:448)
            ... redacted (see end for full error)
==1920==  Address 0x1bd1be1f is 5,599 bytes inside a block of size 7,960 alloc'd
==1920==    at 0x4C2BBAD: malloc (/builddir/build/BUILD/valgrind-3.11.0/coregrind/m_replacemalloc/vg_replace_malloc.c:299)
==1920==    by 0x4F3D3E: GetNewPage (svn/R-devel/src/main/memory.c:879)
            ... redacted (see end for full error)

请注意,这是 1 字节 alloc'd 块内。我已经看到了类似的错误,涉及在空闲块之后或之前写入,甚至写入大小大于块结尾的写入 - 地址(因此溢出),但我找不到像这个。

这发生在R CRAN check farmthis line of code

我无法在 OSX 或 linux VM 上使用 valgrind 在本地重现错误。

除此之外,这个错误对我来说没有意义。为什么我不能在分配的块中间写 1 个字节?这一切都在 R 内部运行,所以我猜有问题的分配是由程序的不同部分进行的,并且它以某种方式被保留(正在发生的一个可能暗示是我从 R 请求的分配小于 60错误出现时的字节),但我不知道这是否是 valgrind 无论如何都能检测到的。

完全错误:

==1920== Invalid write of size 1
==1920==    at 0x4C2ECC7: strcpy (/builddir/build/BUILD/valgrind-3.11.0/memcheck/../shared/vg_replace_strmem.c:506)
==1920==    by 0x1D533B57: CSR_bullet (packages/tests-vg/vetr/src/cstringr.c:448)
==1920==    by 0x1D53317D: CSR_bullet_ext (packages/tests-vg/vetr/src/cstringr-ext.c:107)
==1920==    by 0x4852BD: do_dotcall (svn/R-devel/src/main/dotcode.c:1252)
==1920==    by 0x4C274D: Rf_eval (svn/R-devel/src/main/eval.c:728)
==1920==    by 0x4C3AB5: R_execClosure (svn/R-devel/src/main/eval.c:1617)
==1920==    by 0x4C2391: Rf_eval (svn/R-devel/src/main/eval.c:747)
==1920==    by 0x4C29E0: forcePromise (svn/R-devel/src/main/eval.c:520)
==1920==    by 0x4C27A1: Rf_eval (svn/R-devel/src/main/eval.c:647)
==1920==    by 0x4C7746: do_withVisible (svn/R-devel/src/main/eval.c:2998)
==1920==    by 0x4F7104: do_internal (svn/R-devel/src/main/names.c:1363)
==1920==    by 0x4B553B: bcEval (svn/R-devel/src/main/eval.c:6503)
==1920==  Address 0x1bd1be1f is 5,599 bytes inside a block of size 7,960 alloc'd
==1920==    at 0x4C2BBAD: malloc (/builddir/build/BUILD/valgrind-3.11.0/coregrind/m_replacemalloc/vg_replace_malloc.c:299)
==1920==    by 0x4F3D3E: GetNewPage (svn/R-devel/src/main/memory.c:879)
==1920==    by 0x4F5814: Rf_allocVector3 (svn/R-devel/src/main/memory.c:2659)
==1920==    by 0x4CAEAF: Rf_allocVector (svn/R-devel/src/include/Rinlinedfuns.h:247)
==1920==    by 0x4CAEAF: do_growconst (svn/R-devel/src/main/eval.c:7490)
==1920==    by 0x4B64BD: bcEval (svn/R-devel/src/main/eval.c:6483)
==1920==    by 0x4C2207: Rf_eval (svn/R-devel/src/main/eval.c:624)
==1920==    by 0x4C3AB5: R_execClosure (svn/R-devel/src/main/eval.c:1617)
==1920==    by 0x4BAE13: bcEval (svn/R-devel/src/main/eval.c:6454)
==1920==    by 0x4C2207: Rf_eval (svn/R-devel/src/main/eval.c:624)
==1920==    by 0x4C3AB5: R_execClosure (svn/R-devel/src/main/eval.c:1617)
==1920==    by 0x4BAE13: bcEval (svn/R-devel/src/main/eval.c:6454)
==1920==    by 0x4C2207: Rf_eval (svn/R-devel/src/main/eval.c:624)

【问题讨论】:

  • 可能会继续显示该块何时被删除/释放的消息。
  • 难道不会说“...大小为 7,960 free'd”吗?我链接的完整输出中没有出现“免费”一词。
  • 可能之前的(未捕获的)错误覆盖了内存控制块?
  • ... && *(string_copy + 1)) 为什么要取消换行数中的最后一个 '\n'? (除了奇怪的语法:... && string_copy[1]) 更常见,恕我直言)
  • size_t i = 0; i < newlines; ++i) size_all = CSR_add_szt(size_all, ctd_size); 你在这里通过重复加法进行乘法运算。你害怕一个 size_t 溢出吗?

标签: c r valgrind


【解决方案1】:

使用内存池时可能会发生此类错误。

通常,lib 或应用程序(例如 R)可以构建自己的分配器 通过获得大块,例如从malloc,然后分配小块 从这些大块。 Valgrind 有一些客户端请求允许描述这些块(大块或内部较小的块)及其分配。

对于此类客户端请求,您可能有一部分 malloc 分配块 这实际上被标记为不可寻址。

查看堆栈跟踪条目:

==1920== by 0x4F3D3E: GetNewPage (svn/R-devel/src/main/memory.c:879)

上面的解释看起来很有道理。

这可能表明 R 中的某个地方存在真正的错误 和/或 R 分配器向 valgrind 描述其内存池的方式

【讨论】:

  • 这确实是正在发生的事情。我自己无法重现此错误,因为我没有运行 R 的检测版本,但是一旦我得到了一个,我就能够缩小错误范围。我确实在共享页面的小分配结束后写了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多