我有一套程序与共享内存(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左右--所以复制这个错误的速度可能没有那么快。
因此,可能的泄漏是在:
在这种情况下,是否还有其他工具/lib/hack可以提供帮助?
编辑:询问代码。重复部分是5k行数学题。没有任何拨款,正如我提到的。
但是开始,停止,重复地进入这里:
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%肯定它的零泄漏。试着在他们的邮件列表中找到答案。
发布于 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++,您可以重载新的全局操作符。
https://stackoverflow.com/questions/16913418
复制相似问题