malloc’ing strcat
Florian Weimer
fweimer@redhat.com
Mon Feb 24 21:17:00 GMT 2020
* Alexandre François Garreau:
> Not any more than the current standard strcat functions, which more or
> less behaves the same (except my macro doesn’t buffer overflow, and is not
> destructive, but I could as well make a version that is destructive as
> well using realloc that would fail for a statically allocated first
> argument):
> #define astrcat(a, b) strcat (realloc (a, strlen(a) + strlen (b) + 1), b)
>
> The most often use is to concatenate two strings at a time anyway, so it’s
> already a big step forward to have a self contained interface, rather than
> always repetitively calling malloc with the same arguments and often with
> strcpy combined…
That doesn't match what I see. After all, without garbage collection,
you can't do this:
astrcat (astract (a, b), c)
And multi-concatenations are fairly common:
<https://codesearch.debian.net/search?q=stpcpy.*stpcpy.*stpcpy&literal=0>
>> > But I’m curious, what did C11 change about that?
>>
>> It's possible to use a variadic macro and a compound literal to
>> construct an array in a macro, and pass that (along with the array size)
>> to the actual implementation in a function (whose name would be an
>> implementation detail).
>
> Ohhhh, you mean the function-arg-separators commas would become arrays-
> separators commas, like that?
> #define astrcat(...) _astrcat((char *[]) {__VA_ARGS__, NULL})
> char *
> _astrcat (char *strarray[])
> {
> char * result = malloc(1);
> size_t len = 1;
> off_t i = -1;
> result[0] = '\0';
> while (strarray[++i])
> result = strcat(realloc(result, len += strlen(strarray[i])),
> strarray[i]);
> return result;
> }
I think I wouldn't use the NULL sentinel for the reasons indicated
(silent truncation after memory allocation or other failure, even under
valgrind), and use
sizeof ((const char *[]) { __VA_ARGS__ }) / sizeof (const char *)
to compute the number of arguments, and pass that separately from the
pointer.
>> I don't think this could be done in a portable manner before C11.
>
> Why couldn’t a standard variadic function do? it’s only longer:
> #define astrcat(...) _astrcat (__VA_ARGS__, NULL)
Yes, I meant C99. Compound literals and __VA_ARGS__ were added in C99.
>> > And still, why wasn’t a macro such as the one I presented already
>> > introduced?
>>
>> strdup was only recently added to ISO C, and POSIX is somewhat dormant
>> these days.
>
> but there were already convenient functions before standardizations
> weren’t they? such as the scanf “m” (or “a” I forgot) conversion modifier,
> or vasprintf… right?
asprintf is still a GNU extension. The m scanf modifier is only in
POSIX.
Thanks,
Florian
More information about the Libc-help
mailing list