我正在实现一个基于libudev的USB设备监控代码,它可以在hidraw驱动程序下使用。我实现了网络上的标准示例,并使用valgrind和gdb检查内存泄漏。
/*******************************************
libudev example.
This example prints out properties of
each of the hidraw devices. It then
creates a monitor which will report when
hidraw devices are connected or removed
from the system.
This code is meant to be a teaching
resource. It can be used for anyone for
any reason, including embedding into
a commercial product.
The document describing this file, and
updated versions can be found at:
http://www.signal11.us/oss/udev/
Alan Ott
Signal 11 Software
2010-05-22 - Initial Revision
2010-05-27 - Monitoring initializaion
moved to before enumeration.
*******************************************/
我很不开心地发现一些不应该分配内存的libudev函数正在泄漏。我通过在所有对象都未引用后退出()并查看valgrind报告来追踪此问题。具体而言,以下代码存在泄漏:
int main (void)
{
struct udev *udev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry;
struct udev_device *dev, *devParent;
struct udev_monitor *mon;
int fd;
/* Create the udev object */
udev = udev_new();
if (!udev)
{
printf("Can't create udev\n");
exit(1);
}
/* This section sets up a monitor which will report events when
blah blah....
"hidraw" devices. */
/* Set up a monitor to monitor hidraw devices */
mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, "hidraw", NULL);
udev_monitor_enable_receiving(mon);
/* Get the file descriptor (fd) for the monitor.
This fd will get passed to select() */
fd = udev_monitor_get_fd(mon);
/* Create a list of the devices in the 'hidraw' subsystem. */
enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
if (1)
{
// leak debug block
udev_enumerate_unref(enumerate);
udev_monitor_unref(mon);
udev_unref(udev);
return 0;
}
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
/* For each item enumerated, print out its information.
以下是valgrind的输出:
==11424== HEAP SUMMARY:
==11424== in use at exit: 4,096 bytes in 1 blocks
==11424== total heap usage: 11 allocs, 10 frees, 28,086 bytes allocated
==11424==
==11424== LEAK SUMMARY:
==11424== definitely lost: 0 bytes in 0 blocks
==11424== indirectly lost: 0 bytes in 0 blocks
==11424== possibly lost: 0 bytes in 0 blocks
==11424== still reachable: 4,096 bytes in 1 blocks
==11424== suppressed: 0 bytes in 0 blocks
==11424== Rerun with --leak-check=full to see details of leaked memory
如果我将“泄漏调试块”放在其上方一行的位置,valgrind会以0字节泄漏的干净结果退出。 如果我将该块向下移动一行,则下一个函数将增加泄漏大小和组件:
==14262== in use at exit: 8,192 bytes in 2 blocks
==14262== total heap usage: 45 allocs, 43 frees, 150,907 bytes allocated
==14262==
==14262== LEAK SUMMARY:
==14262== definitely lost: 0 bytes in 0 blocks
==14262== indirectly lost: 0 bytes in 0 blocks
==14262== possibly lost: 0 bytes in 0 blocks
==14262== still reachable: 8,192 bytes in 2 blocks
==14262== suppressed: 0 bytes in 0 blocks
==14262== Rerun with --leak-check=full to see details of leaked memory
在下一行之后情况变得更糟,这令我担忧,因为我的代码需要运行多年,这样的泄漏可能会无限制地累积。
有什么建议可以避免这种情况发生,如何控制它?
code
udev_enumerate_add_match_subsystem(enumerate, "hidraw");。valgrind dump 如下:==20471== HEAP SUMMARY: ==20471== 在退出时使用: 1个块中的4,096字节 ==20471== 总堆使用量: 11次分配,10次释放,已分配28,086字节 ==20471== 仍然可以在损失记录1/1(在/lib/i386-linux-gnu/libudev.so.1.6.5中)中找到1个块中的4,096字节 ==20471== 由0x108BAA: main (in /home/pi/projects/eclipse/testUSB/udevHidraw) ==20471== LEAK SUMMARY: ==20471== 仍然可达: 1个块中的4,096字节 - David Gabbay