c-G-WAN与valgrind?备选方案



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 64位)。

问题是:
1) G-WAN应该和valgrind一起工作吗
2) 有没有其他可行的选择来检测在G-WAN下运行的C代码中的内存错误?

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年以来,并发是"唯一"的主流……大约十年前。

相关内容

  • 没有找到相关文章

最新更新