strdupa() in C - Dangers and Duplicates

2019-07-14 04:47发布

I make programs in C. I read about the strdup() function. From what I could tell, the strdup() function allocates space while the strcpy() does not. But the problem with strdup() is it allocates space but does not free it. strdupa() allocates and frees space. But at some places I read that the strdupa() function is dangerous. It would be helpful if someone could tell me why strdupa() is dangerous. Also, when I tried to run a program in my Open Suse 12.1 32 bit system, gcc, gave an error which told that strdupa() does not exist. If strdupa() is a dangerous function, can someone tell me the duplicate of strdupa() and the headers to use when using the function.

标签: c strdup
1条回答
神经病院院长
2楼-- · 2019-07-14 05:29

The strdupa() function is documented to use the alloca() function to allocate memory. That means its memory is freed when the function returns. The alloca() function is not singularly portable; the strdupa() function is likewise not all that portable.

The manual page documents that the strdupa() function is only available when you compile with -D_GNU_SOURCE, or if you use gcc -std=gnu11 or something similar.

If you need to access the memory after the function that calls strdupa() returns, then you cannot use strdupa()strdup() is necessary. If you're worried about portability, you probably use strdup(), though even that is only defined by 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. AFAIK, alloca() is not part of either POSIX or the proposed extensions to the Standard C library.


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

It depends on your definition of 'danger'. Yes. If there isn't enough space on the stack for the string, then strdupa() will fail when strdup() won't. There are those who are not enamoured of alloca() and therefore they are not keen on code that uses alloca(). The alloca() manual page has an extensive set of notes about the problems, one of which is that you can't tell when alloca() has failed.

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

You look for core dumps; if the program crashes, it was perhaps because of an alloca() allocation failure. Using valgrind might spot the problem; you still can't reliably recover from the problem, though, and you probably won't have your production code running under valgrind, so it is at most a diagnostic aid. If you want reliable behaviour, use strdup() — and accept that you need to manually free the allocated memory.

From the manual page for 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.

查看更多
登录 后发表回答