我用 C 编写程序。我读到了这个strdup()
函数。据我所知,该strdup()
函数分配空间而strcpy()
没有分配空间。但问题strdup()
是它分配空间但不释放它。strdupa()
分配和释放空间。但是在某些地方,我读到该strdupa()
功能很危险。如果有人能告诉我为什么strdupa()
危险,那将很有帮助。此外,当我尝试在我的 Open Suse 12.1 32 位系统中运行程序时,gcc给出了一个错误,提示strdupa()
不存在。如果strdupa()
是一个危险的功能,有人可以告诉我strdupa()
使用该功能时要使用的副本和标题。
1 回答
该strdupa()
函数被记录为使用该alloca()
函数来分配内存。这意味着它的内存在函数返回时被释放。该alloca()
功能不是特别可移植的;该strdupa()
功能同样不是那么便携。
手册页记录了该strdupa()
功能仅在您编译时可用-D_GNU_SOURCE
,或者如果您使用gcc -std=gnu11
或类似的东西。
如果在调用的函数strdupa()
返回后需要访问内存,那么就不能使用strdupa()
-strdup()
是必要的。如果您担心可移植性,您可能会使用strdup()
,尽管它仅由 POSIX ( strdup()
) 而非标准 C 定义。请注意,这strdup()
是TR 24731-2: Extensions to the C Library - Part II: Dynamic allocation functions 的一部分. AFAIK,alloca()
既不是 POSIX 的一部分,也不是标准 C 库的提议扩展的一部分。
使用“strdupa()”有什么危险吗?
这取决于你对“危险”的定义。是的。如果堆栈上没有足够的空间存放字符串,那么当不会strdupa()
时会失败strdup()
。有些人不喜欢,alloca()
因此他们不热衷于使用alloca()
. 手册页有大量关于问题的alloca()
注释,其中一个是您无法判断何时alloca()
失败。
是否有检查
alloca()
故障的工具——例如valgrind
内存泄漏?
您寻找核心转储;如果程序崩溃,可能是因为alloca()
分配失败。使用valgrind
可能会发现问题;但是,您仍然无法可靠地从问题中恢复,并且您的生产代码可能不会valgrind
在 . 如果您想要可靠的行为,请使用strdup()
- 并接受您需要手动释放分配的内存。
从手册页alloca()
注意
该alloca()
函数依赖于机器和编译器。对于某些应用程序,与使用 malloc(3) 和 free(3) 相比,使用它可以提高效率。在某些情况下,它还可以简化使用 longjmp(3) 或 siglongjmp(3) 的应用程序中的内存释放。否则,不鼓励使用它。因为分配的空间
alloca()
是在堆栈帧中分配的,所以如果函数返回被调用 longjmp(3) 或 siglongjmp(3) 跳过,则该空间会自动释放。不要试图释放 (3) alloca() 分配的空间!
GNU 版本注意事项
通常,gcc(1) 将调用转换alloca()
为内联代码。当给出-ansi
,-std=c89
,-std=c99
, 或选项时(并且不包括-fno-builtin
标题),这不会完成。<alloca.h>
但要小心!默认情况下,glibc 版本的<stdlib.h>
include<alloca.h>
包含以下行:#define alloca(size) __builtin_alloca (size)
如果有人拥有此功能的私有版本,则会产生混乱的后果。
代码被内联的事实意味着不可能获取这个函数的地址,或者通过链接不同的库来改变它的行为。
内联代码通常由一条调整堆栈指针的指令组成,并且不检查堆栈溢出。因此,没有 NULL 错误返回。
错误
如果堆栈帧无法扩展,则没有错误指示。(但是,在分配失败后,如果程序尝试访问未分配的空间,它很可能会收到 SIGSEGV 信号。)在许多系统
alloca()
上不能在函数调用的参数列表中使用,因为保留的堆栈空间alloca()
将出现在函数参数空间中间的堆栈上。