2

G-WAN 是一种开箱即用的在 Web 上运行 C 代码的便捷方式,但对我而言,它不适用于 valgrind。(运行valgrind ./gwan有错误信息Inconsistency detected by ld.so: rtld.c: 1292: dl_main: Assertion `_rtld_local._dl_rtld_map.l_libname' failed!然后退出;系统是 Debian Jessie 64bit)。

问题是:
1)G-WAN 是否应该与 valgrind 一起使用?
2) 是否有任何其他可行的选项来检测在 G-WAN 下运行的 C 代码中的内存错误?

4

1 回答 1

1

G-WAN 应该与 valgrind 一起使用吗?

我们已经测试了 Valgrind,虽然它做了很多正确的事情,但它不适合高并发作业(即使是低并发也是 Valgrind 的一个问题)。

检测在 G-WAN 下运行的 C 代码中的内存错误的可行选项?

使用malloc()包装器、预先分配的池,甚至更好,alloca()首先用于避免内存问题。

请注意,G-WAN 处理 C 脚本中的错误指针而不会使服务器崩溃,请参阅: http: //gwan.ch/developers#crash

这个错误的代码:

int main(int argc, char *argv[])
{
   strcpy(0xBADC0DE, 0xBADC0DE);
   return 200;
}

...将产生类似于以下“优雅”崩溃报告的内容:

Script: crash_libc.c
 Client: 127.0.0.1
 Query : ?crash_libc

 Signal        : 11:Address not mapped to object
 Signal src    : 1:SEGV_MAPERR
 errno         : 0
 Thread        : 0
 Code   Pointer: 0000f5200b33 (module:/lib/libc.so.6, function:strcpy, line:0)
 Access Address: 00000badc0de

 Registers     : EAX=00000badc0de CS=00000033 EIP=0000f5200b33 EFLGS=000000010202
                 EBX=000000000001 SS=ec2d8ed4 ESP=0000f5ded828 EBP=0000f5dee020
                 ECX=000033323130 DS=ec2d8ed4 ESI=0000ec2d8f86 FS=00000033
                 EDX=000003b03c00 ES=ec2d8ed4 EDI=00000badc0de CS=00000033

 Module        :Function        :Line # PgrmCntr(EIP)  RetAddress  FramePtr(EBP)
      libc.so.6:          strcpy:     - 0000f5200b33 0000ec2d8f00   0000f5dee020
        servlet:            main:    37 0000ec2d8f00 00000042e10c   0000f5dee020        

G-WAN 甚至会告诉您源代码中的错误发生在哪里(参见 G-WAN crash_xxx.c 示例),而不是终止服务器进程。

如果您不想调试 C 代码,请使用 Java 或 Scala(均受 G-WAN 支持) - 您将需要更多内存,因为您的数据将保持加载,直到 GC 减慢所有内容以释放它认为可以的内容被释放 - 但至少你会享受更少的内存相关错误,如果有的话。


根据提问者的要求,这里有更多详细信息。

在 2012 年末,我们测试了十几个免费和商业工具,比如 Valgrind,它们应该有助于调试并发。我们还使用静态工具研究源代码,而不仅仅是用于运行(编译)程序的动态工具。

可悲的事实是,他们都有共同的问题,他们:

  • 通常太慢而无法支持并发(核心问题)
  • 产生无数次琐碎的警报(甚至更多的错误警报)
  • 非常昂贵(当然是商业的)并且在购买之前不能总是进行测试(!)

因此,经过数周检查和过滤所有这些结果后,我们花费了大量时间“纠正”G-WAN 代码库,以消除琐碎和错误的警报(由无法区分有效代码和错误代码的工具引起的警报)。 .. 但是,令我们当时感到沮丧的是,我们没有在 G-WAN 中发现任何真正的错误(明确表示那几周是浪费时间)。

因此,上面的结论是:尽可能编写简单的代码,并在需要更复杂的策略时尝试预先分配块。

当然,Linux LIBC 坚持用(不可捕获的)abort信号杀死应用程序这一事实并没有帮助(这会阻止程序恢复或转储相关跟踪),尤其是对于草率的双释放 Linux LIBC 检测(它错误地假设所有代码都在使用它的 malloc() 当程序曾经使用过 malloc() 时——这通常是由 LIBC 调用完成的!)。我什至不是在谈论 mmap() 失败,也不是在谈论 OOM 终止开关。

到目前为止,我们发现唯一可行的解​​决方案是避免使用 Linux LIBC,并使用我们自己的 C 运行时编译我们需要的所有内容。对于所有用户来说,这有点难以推荐为“要做的事情”,但它对我们有用。

我们很高兴看到我们的部分代码(或至少在 G-WAN 中实现的一些概念)被 Linux 使用,因为这将使我们(以及许多其他开发人员之一)的生活变得更加轻松,但是联系方式我们过去对“负责人”的看法并不令人鼓舞。

总而言之,操作系统、像我们这样的 ISV 以及开发人员都有改进的空间——毕竟,自 2004 年以来,并发是“唯一的”主流......大约十年前。

于 2013-07-16T12:34:29.753 回答