C 中的 strdupa() - 危险和重复

strdupa() in C - Dangers and Duplicates

我用 C 编写程序。我阅读了 strdup() 函数。据我所知,strdup() 函数分配了 space 而 strcpy() 没有。但是 strdup() 的问题是它分配了 space 但没有释放它。 strdupa() 分配和释放 space。但在某些地方,我读到 strdupa() 函数是危险的。如果有人能告诉我为什么 strdupa() 是危险的,那将会很有帮助。此外,当我尝试 运行 我的 Open Suse 12.1 32 位系统中的程序时,gcc 给出了一个错误,提示 strdupa() 不存在。如果 strdupa() 是一个危险的函数,有人可以告诉我 strdupa() 的副本和 headers 在使用该函数时要使用的副本。

strdupa() function is documented to use the alloca()函数分配内存。这意味着它的内存在函数 returns 时被释放。 alloca() 函数不是唯一可移植的; strdupa() 功能也不是那么便携。

手册页记录了 strdupa() 函数仅在您使用 -D_GNU_SOURCE 编译时可用,或者如果您使用 gcc -std=gnu11 或类似的东西。

如果你需要在调用strdupa()returns的函数之后访问内存,那么你不能使用strdupa()——strdup()是必须的。如果您担心可移植性,您可能会使用 strdup(),尽管它仅由 POSIX 定义(strdup()) and not by Standard C. Note that strdup() is part of TR 24731-2: Extensions to the C Library - Part II: Dynamic allocation functions。据我所知,alloca() 不属于 POSIX 或建议的标准 C 库扩展。


Is there any danger in using 'strdupa()'?

这取决于你对'danger'的定义。是的。如果堆栈上没有足够的 space 用于字符串,则 strdupa() 将失败,而 strdup() 不会。有些人不喜欢 alloca(),因此他们不热衷于使用 alloca() 的代码。 alloca() 手册页有大量关于这些问题的注释,其中之一是您无法判断 alloca() 何时失败。

Is there a tool to check for alloca() failures — such as valgrind for memory leaks?

您寻找核心转储;如果程序崩溃,可能是因为 alloca() 分配失败。使用 valgrind 可能会发现问题;但是,您仍然无法可靠地从问题中恢复,并且您可能不会将生产代码 运行 置于 valgrind 下,因此它至多是一种诊断辅助工具。如果您想要可靠的行为,请使用 strdup() — 并接受您需要手动释放分配的内存。

来自 alloca()

的手册页

Notes
The alloca() function is machine- and compiler-dependent. For certain applications, its use can improve efficiency compared to the use of malloc(3) plus free(3). In certain cases, it can also simplify memory deallocation in applications that use longjmp(3) or siglongjmp(3). Otherwise, its use is discouraged.

Because the space allocated by alloca() is allocated within the stack frame, that space is automatically freed if the function return is jumped over by a call to longjmp(3) or siglongjmp(3).

Do not attempt to free(3) space allocated by alloca()!

Notes on the GNU version
Normally, gcc(1) translates calls to alloca() with inlined code. This is not done when either the -ansi, -std=c89, -std=c99, or the -fno-builtin option is given (and the header <alloca.h> is not included). But beware! By default the glibc version of <stdlib.h> includes <alloca.h> and that contains the line:

#define alloca(size)   __builtin_alloca (size)

with messy consequences if one has a private version of this function.

The fact that the code is inlined means that it is impossible to take the address of this function, or to change its behavior by linking with a different library.

The inlined code often consists of a single instruction adjusting the stack pointer, and does not check for stack overflow. Thus, there is no NULL error return.

Bugs
There is no error indication if the stack frame cannot be extended. (However, after a failed allocation, the program is likely to receive a SIGSEGV signal if it attempts to access the unallocated space.)

On many systems alloca() cannot be used inside the list of arguments of a function call, because the stack space reserved by alloca() would appear on the stack in the middle of the space for the function arguments.