为什么strdup被认为是邪恶的

我看过一些海报,说明strdup是邪恶的。 对此有共识吗? 我使用它没有任何内疚感,并且没有理由比使用malloc / memcpy更糟糕。

我唯一可以想到的可能是获得声誉的是调用者可能会滥用它(例如,没有意识到他们必须释放返回的内存;尝试strcat到strdup’ed字符串的末尾)。 但是,malloc的字符串也没有被滥用的可能性。


感谢对那些认为这个问题无益的人的回复和道歉(投票结束)。 总结一下这些回复,似乎没有普遍认为strdup本身就是邪恶的,但是普遍认为它可以像C的许多其他部分一样被不正当地或不安全地使用。

真的没有’正确’的答案,但为了接受一个,我接受了@nneoneo的答案 – 它同样可能是@R ..的答案。

我能想到的两个原因:

  1. 它不是严格的ANSI C,而是POSIX。 因此,一些编译器(例如MSVC)不鼓励使用(MSVC更喜欢_strdup ),并且从技术上讲 ,C标准可以用不同的语义定义自己的strdup ,因为str是保留的前缀。 因此,它的使用存在一些潜在的可移植性问题。
  2. 它隐藏了内存分配。 大多数其他str函数不分配内存,因此用户可能被误导(正如你所说)相信返回的字符串不需要被释放。

但是,除了这些观点之外,我认为仔细使用strdup是合理的,因为它可以减少代码重复并为常见习语(例如strdup("constant string")提供一个很好的实现,以获得一个可变的,可返回的副本文字字符串)。

我的答案是支持strdup而且它并不比C中的任何其他函数差。

  1. POSIX是一个标准 ,如果可移植性成为一个问题, strdup并不难实现。

  2. 如果有人花一点时间阅读手册页并了解strdup是如何工作的,是否释放strdup分配的内存应该不是问题。 如果一个人不理解一个函数是如何工作的,那么这个人很可能会弄乱一些东西,这适用于任何函数,而不仅仅是strdup

  3. 在C中,内存和大多数其他东西都是由程序员管理的,因此strdup并不比忘记释放 malloc内存,无法终止字符串,在scanf使用不正确的格式字符串(并调用未定义的行为),访问悬空更糟糕指针等

(我真的想发布这个评论,但无法添加一条评论。因此,将其作为答案发布)。

我没有真正听到被描述为邪恶的strdup ,但有些人不喜欢它的一些可能的原因:

  1. 它不是标准C(但在POSIX中)。 但是我发现这个理由很愚蠢,因为它几乎是一个单行函数,可以添加到缺少它的系统上。
  2. 盲目地在整个地方复制字符串,而不是在可能的情况下就地使用它们浪费时间和内存,并将故障情况引入代码,否则可能无故障。
  3. 当你确实需要一个字符串的副本时,你可能真的需要更多的空间来修改或构建它,而strdup并没有给你这个。

我认为对strdup的大多数关注来自于缓冲区运行和字符串格式不正确的安全问题。 如果将非空终止字符串传递给strdup,则可以分配未定义的长度字符串。 我不知道这是否可以专门用于攻击,但一般来说,只使用最大长度的字符串函数而不是单独依赖空字符是一种良好的安全编码习惯。

许多人显然不这样做,但我个人认为有几个原因strdup恶事,

  • 主要是隐藏分配。 其他str*函数和大多数其他标准函数之后不需要free ,因此strdup看起来非常无害,你可以忘记清理它。 dmckee建议将它添加到需要清理的function列表中,但为什么呢? 我没有看到将两条中长线减少到一条短线的巨大优势。

  • 它总是在堆上分配内存,而对于C99(它是99?)的VLA,你还有另一个原因就是使用strcpy (你甚至不需要malloc )。 你不能总是这样做,但是当你可以的时候,你应该这样做。

  • 它不是ISO标准的一部分(但它是POSIX标准的一部分,感谢Wiz),但这确实是一个小点,因为R ..提到它可以轻松添加。 如果您编写可移植程序,我不知道您是如何判断它是否已经定义但是…

这些当然是我自己的一些原因,没有其他人的原因。 为了回答你的问题,我没有达成共识。

如果你正在为自己编写程序并且你发现strdup没有问题,那么没有理由不使用它,而不是你正在编写一个程序,以便被许多技能水平和年龄的人阅读。

不喜欢strdup的原因是没有提到的是没有自然配对的资源分配。 让我们尝试一个愚蠢的游戏:我说malloc ,你说是free 。 我说open你说close 。 我说create你说destroy 。 我说strdup你说….?

实际上, strdup的答案当然是free的,并且函数可以更好地命名为malloc_and_strcpy以使其清楚。 但许多C程序员并没有这样想,并忘记了strdup需要它的对立或“结束” free解除分配。

根据我的经验,在调用strdup代码中发现内存泄漏是很常见的。 这是一个奇怪的function,它结合了strlenmallocstrcpy