对于有缺陷、内存泄漏的 POSIX API,我们该怎么办?

发布于 2024-10-14 01:21:51 字数 1165 浏览 9 评论 0原文

免责声明:这是一个分配,但分配并不要求我们消除内存泄漏。我只是对这个有保留。

考虑以下方法:

//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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

百合的盛世恋 2024-10-21 01:21:51

这可能是误报。 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!

烟柳画桥 2024-10-21 01:21:51

单一 UNIX ® 规范版本 2 不保证静态数据将使用时,它说它“可能是静态的”。

如果 s 是空指针,则
表示是在一个区域中生成的
这可能是静态的(因此
被后续调用覆盖
cuserid()),其地址为
返回。

cuserid() 的 Linux 手册页有两个挑衅性的陈述:

cuserid 函数包含在 1988 版本的 POSIX 中,但从 1990 版本中删除。

没有人确切知道 cuserid() 的作用 - 在便携式中避免使用它
程序 - 完全避免它 - 使用
getpwuid(geteuid()) 相反,如果那样
就是你
的意思。不要使用 cuserid()。

假设 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".

If s is a null pointer, this
representation is generated in an area
that may be static (and thus
overwritten by subsequent calls to
cuserid()), the address of which is
returned.

The linux man page for cuserid() has two provocative statements:

The cuserid function was included in the 1988 version of POSIX, but removed from the 1990 version.

and

Nobody knows precisely what cuserid() does - avoid it in portable
programs - avoid it altogether - use
getpwuid(geteuid()) instead, if that
is what you
meant. DO NOT USE cuserid().

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文