为什么strdup被认为是邪恶的

Wil*_*ris 26 c c-strings

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

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


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

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

nne*_*neo 32

我能想到的两个原因:

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

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


P.P*_*.P. 20

我的答案是相当支持strdup,它并不比C中的任何其他功能更糟糕.

  1. POSIX是一种标准,strdup如果可移植性成为问题,则实现起来并不困难.

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

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

(我真的想把它作为评论发布,但不能添加一条评论.因此,将其作为答案发布).


R..*_*R.. 10

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

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


joh*_*les 5

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

  • 如果将一个非null终止的字符串传递给任何需要空终止字符串的函数,那么程序员就会非常糟糕. (5认同)
  • 对于大多数实际用途,我不使用`strncpy()`.它不保证空终止.如果将5字节字复制到20 KiB缓冲区,它还会写入20475个空值.这两种行为都不能为我所接受.通常情况下,我确定我知道字符串有多长并使用`memmove()`或(偶尔)`memcpy()`; 我确实有复发并使用`strcpy()`,但前提是我知道有足够的空间.(如果是任何安慰,`strncat()`比`strncpy()`更差;我从不使用它!)如果我不知道字符串的最大长度,我无法安全地操纵它.我不知道它甚至可以被截断. (2认同)
  • 根据定义,没有空终止的char数组不是"字符串".当你给它一个http URL而不是一个文件路径时,你不会指望`fopen()`工作.任何给普通字符串数组提供正常字符串数组的程序员应该允许RTFM或者不允许在任何生产代码的100米范围内.他们很可能也忘记检查`malloc()`的返回值是否为NULL. (2认同)