对于有缺陷、内存泄漏的 POSIX API,我们该怎么办?
免责声明:这是一个分配,但分配并不要求我们消除内存泄漏。我只是对这个有保留。
考虑以下方法:
//Prints the current user ID to the console.
void PrintUserId()
{
std::cout << "Current User Id: " << cuserid(0) << std::endl;
}
cuserid
状态的文档:
如果字符串不是空指针,则它应该是一个至少可以容纳L_cuserid字符的数组;字符串在此数组中返回。否则,返回指向静态区域中字符串的指针。
但至少在我的系统上,有问题的内存似乎不是静态分配的(或者至少有错误......):
(Valgrind Output) ==4488== 160 (40 direct, 120 indirect) bytes in 1 blocks are definitely lost in loss record 11 of 11 ==4488== at 0x4025BD3: malloc (vg_replace_malloc.c:236) ==4488== by 0x4247A9C: nss_parse_service_list (nsswitch.c:622) ==4488== by 0x4248216: __nss_database_lookup (nsswitch.c:164) ==4488== by 0x402DEAB: ??? ==4488== by 0x402EB6C: ??? ==4488== by 0x41FE41C: getpwuid_r@@GLIBC_2.1.2 (getXXbyYY_r.c:253) ==4488== by 0x41A2785: cuserid (cuserid.c:38) ==4488== by 0x80495A3: PrintUserId() (in /home/bro4/Assignment1.bin) ==4488== by 0x8049A11: ParentProcess() (in /home/bro4/Assignment1.bin) ==4488== by 0x8049B53: main (in /home/bro4/Assignment1.bin)
我只是坚持这一点吗?
Disclaimer: This is for an assignment, but the assignment doesn't require that we remove memory leaks. I'm just anal retentive on this one.
Consider the following method:
//Prints the current user ID to the console.
void PrintUserId()
{
std::cout << "Current User Id: " << cuserid(0) << std::endl;
}
The docs for cuserid
state:
If string is not a null pointer, it should be an array that can hold at least L_cuserid characters; the string is returned in this array. Otherwise, a pointer to a string in a static area is returned.
But at least on my system, the memory in question doesn't appear to be statically allocated (or at least there are bugs...):
(Valgrind Output) ==4488== 160 (40 direct, 120 indirect) bytes in 1 blocks are definitely lost in loss record 11 of 11 ==4488== at 0x4025BD3: malloc (vg_replace_malloc.c:236) ==4488== by 0x4247A9C: nss_parse_service_list (nsswitch.c:622) ==4488== by 0x4248216: __nss_database_lookup (nsswitch.c:164) ==4488== by 0x402DEAB: ??? ==4488== by 0x402EB6C: ??? ==4488== by 0x41FE41C: getpwuid_r@@GLIBC_2.1.2 (getXXbyYY_r.c:253) ==4488== by 0x41A2785: cuserid (cuserid.c:38) ==4488== by 0x80495A3: PrintUserId() (in /home/bro4/Assignment1.bin) ==4488== by 0x8049A11: ParentProcess() (in /home/bro4/Assignment1.bin) ==4488== by 0x8049B53: main (in /home/bro4/Assignment1.bin)
Am I just stuck on this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可能是误报。
cuserid
或其依赖项可以在第一次调用时分配缓冲区,然后在下一次调用时释放或重用它。尝试循环调用它;您最终会收到多个泄漏报告吗?在您的情况下,分配是由 nss_parse_service_list,nsswitch 内部 API 的一部分,用于处理各种身份验证提供程序(unix /etc/passwd、LDAP 等)之间的切换。此函数由 __nss_database_lookup,它将其称为一次性初始化过程的一部分。所以这并不是真正的泄漏;而是泄漏。它是分配用于保存解析配置文件(或者在本例中为默认配置)的结果的内存。它不会被释放,因为在程序终止之前都需要它;但它也不会增长。
由于这是误报,您可能需要禁止这些报告< /a> 在 valgrind 中。从系统库中看到 valgrind 警告并不罕见 - 在各种库例程中都有这样的一次性分配,以及低级例程做的事情看起来对 valgrind 来说是一个潜在的问题,而实际上它们非常小心受控且正确。最好压制它们——当然,在检查它们确实不是你的错之后!
It might be a false positive.
cuserid
or its dependencies could allocate a buffer on its first call, then free or reuse it on the next call. Try calling it in a loop; do you end up with multiple leak reports?In your case, the allocation is done by nss_parse_service_list, part of the nsswitch internal API that handles switching between various authentication providers (unix /etc/passwd, LDAP, etc). This function is called by __nss_database_lookup, which calls it as part of a one-time initialization process. So this isn't really a leak; it's memory that's allocated to hold the results of parsing a config file (or, in this case, a default config). It won't be freed, because it's needed until the program terminates; but neither will it grow.
Since this is a false positive, you may want to suppress these reports in valgrind. It's not uncommon to see valgrind warnings from system libraries - there are one-time allocations like this in various library routines, as well as low-level routines doing things that look to valgrind like a potential problem, when in fact they're very carefully controlled and correct. It's best to suppress them - after, of course, checking that they're not really your fault, of course!
单一 UNIX ® 规范版本 2 不保证静态数据将使用时,它说它“可能是静态的”。
cuserid() 的 Linux 手册页有两个挑衅性的陈述:
和
假设 20 多年前该函数已从 POSIX 中删除的说法是准确的,我会说“不要使用 cuserid()”是一个很好的建议。如果失败,请将指针传递给 cuserid 并自行管理内存。
The Single UNIX ® Specification, Version 2 does not guarantee that static data will be used, it says it "may be static".
The linux man page for cuserid() has two provocative statements:
and
Assuming the statement that this function was removed from POSIX more than 20 years ago is accurate, I would say "DO NOT USE cuserid()" is pretty good advice. Failing that, pass a pointer to cuserid and manage the memory yourself.