首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >不费吹灰之力地寻找内存泄漏

不费吹灰之力地寻找内存泄漏
EN

Stack Overflow用户
提问于 2013-06-04 08:47:44
回答 1查看 3.8K关注 0票数 4

我有一套程序与共享内存(ipc)一起工作~48 of。

运行在Linux3.6.0-Rc5上的程序,编写了普通C,在主计算机上编译的gcc负载平均为6.0,每10秒跳到16.0次(24个内核)。

一个代理通过0mq (3.2.3,从同一网络中的12台机器接收1000 msgs/s )从其他机器接收数据,将许多(<50)的工作人员写入共享内存中,读取这些数据并进行一些计算。

代理使用大约20%的cpu,每个工作人员使用1%的CPU,定期跳转10%。

所有程序在执行init()中的所有分配时都是这样写的--在程序启动时调用,在exit ()中调用,在退出前调用。

完全不使用malloc/calloc/free的重复代码。

但这两个程序仍有漏洞。大约每分钟120到240字节。这个内存在7-8天内耗尽,我只是开始/停止进程,但是每次监控应用程序报告我重启的时候,这些泄露的字节都在吞噬我的大脑:)

不好的事情--我不能因为使用共享内存而运行英勇--它只是停止分配/附加共享内存,然后一切都开始崩溃了。

为了找到这个漏洞,我已经开发了代理的剥离版本--没有泄漏,但是我不能用相同数量的数据来填充它。

当在gdb下运行时仍然没有泄漏,但是速度下降了2/3左右--所以复制这个错误的速度可能没有那么快。

因此,可能的泄漏是在:

  • 我的密码。但是没有malloc/calloc。只是指针+-,memcpy,memcmp
  • 一些标准图书馆。滑翔?赛斯洛格?
  • 使用多个源的0mq (不要认为每秒1k/msgs的流量过大)

在这种情况下,是否还有其他工具/lib/hack可以提供帮助?

编辑:询问代码。重复部分是5k行数学题。没有任何拨款,正如我提到的。

但是开始,停止,重复地进入这里:

代码语言:javascript
运行
复制
int main(int argc, char **argv)
{
    ida_init(argc, argv, PROXY);
    ex_pollponies(); // repetive
    ida_destroy();
    return(0);
}


// with some cuttings

int ex_pollponies(void)
{
  int i, rc;
  unsigned char buf[90];
  uint64_t fos[ROLLINGBUFFERSIZE];
  uint64_t bhs[ROLLINGBUFFERSIZE];
  int bfcnt = 0;

  uint64_t *fo;
  uint64_t *bh;

  while(1) {
    rc = zmq_poll(ex_in->poll_items, ex_in->count, EX_POLL_TIMEOUT);
    for (i=0; i < ex_in->count; i++) {
      if (ex_in->poll_items[i].revents & ZMQ_POLLIN) {

        if (zmq_recv(ex_in->poll_items[i].socket, &buf, max_size, 0) == 0)
          continue;
        fo = &fos[bfcnt];
        bh = &bhs[bfcnt];
        bfcnt++;
        if (bfcnt >= ROLLINGBUFFERSIZE)
          bfcnt = 0;

        memcpy(fo, (void *)&buf[1], sizeof(FRAMEOBJECT));
        memcpy(bh, &buf[sizeof(FRAMEOBJECT)+1], sizeof(FRAMEHASH));

        // then store fo, bh into shared memory, with some adjusting and checkings
        // storing every second around 1000 msgs 16 bytes each. But leaking is only 200 bytes per minute.

      }
     }

  }
}

edit2:

我终于让val差事起作用了--只要使用一部分数据(6GB),它最终就通过了。没有发现任何泄漏。但是,在工作过程中,它需要100%的cpu,而且我的程序肯定没有处理所有传入的数据--它不是满负荷工作的。这一半证实了我的气喘猜测泄漏在数据交换块上。我找到了关于mtrace (libc的一部分)的信息,它帮助我跟踪泄漏的地址--它在我的代码之外,在一个线程中。我的代码中唯一的线程是由zeromq创建的。然后,我开始使用套接字选项(增加hwm、缓冲区)和泄漏速度下降,但即使在荒谬的大值上也没有完全消失:

所以,现在我95%肯定它的零泄漏。试着在他们的邮件列表中找到答案。

EN

回答 1

Stack Overflow用户

发布于 2013-06-04 14:52:57

如果valgrind没有解决这个问题,你可以自己跟踪内存分配。

有两种方法--将对malloc的调用替换为对您自己版本的malloc和free的调用,并传递给这些函数某种类型的标识符,比如文件LINE,或者您可以传递正在分配的系统的名称。

在非内存泄漏检测模式中,您直接通过malloc和free,而在内存泄漏检测模式中,您首先记录分配和空闲调用,然后调用malloc和free。当程序完成时,您将匹配分配并释放,您将看到内存泄漏的位置。

您可以使用宏来完成这个任务,这样您的常规构建就不会慢下来。

您不会捕捉到客户端库中无法自己重新编译的泄漏。

另一种方法是使用gcc的-wrap标志,在链接时间让gcc调用您的malloc/free版本,而不是glibc。见这篇文章:

Create a wrapper function for malloc and free in C

这样做的好处是,您还可以记录客户端库中的分配。缺点是您只能使用相同的函数签名,因此无法在泄漏检查器中获得文件

如果这是C++,您可以重载新的全局操作符。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16913418

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档