473,779 Members | 2,078 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

strndup: RFC

Hi
Reading comp.std.c I noticed that there was a message like this:
The WG14 Post Portland mailing is now available from the WG14 web site
at http://www.open-std.org/jtc1/sc22/wg14/

Best regards
Keld Simonsen

I went there and found that there is a report called
ISO/IEC JTC1 SC22 WG14 WG14/N1193
Specification for Safer C Library Functions —
Part II: Dynamic Allocation Functions

It proposes really interesting functions, among others getline and
getdelim, that I introduced into lcc-win32 (by coincidence) a few weeks
ago.

It proposes strdup and strndup too. Lcc-win32 proposes already strdup,
but strndup was missing. Here is a proposed implementation. I would like
to see if your sharp eyes see any bug or serious problem with it.

Thanks in advance

jacob
---------------------------------------------------------cut here
#include <string.h>
#include <stdlib.h>
/*
The strndup function copies not more than n characters (characters that
follow a null character are not copied) from string to a dynamically
allocated buffer. The copied string shall always be null terminated.
*/
char *strndup(const char *string,size_t s)
{
char *p,*r;
if (string == NULL)
return NULL;
p = string;
while (s 0) {
if (*p == 0)
break;
p++;
s--;
}
s = (p - string);
r = malloc(1+s);
if (r) {
strncpy(r,strin g,s);
r[s] = 0;
}
return r;
}

#ifdef TEST
#include <stdio.h>
#define MAXTEST 60
int main(void)
{
char *table[MAXTEST];
char *str = "The quick brown fox jumps over the lazy dog";

for (int i=0; i<MAXTEST;i++) {
table[i] = strndup(str,i);
}
for (int i=0; i<MAXTEST;i++) {
printf("[%4d] %s\n",i,table[i]);
}
return 0;
}
#endif
Dec 2 '06
68 7074
Thad Smith a écrit :
jacob navia wrote:
>It proposes strdup and strndup too. Lcc-win32 proposes already strdup,
but strndup was missing. Here is a proposed implementation. I would like
to see if your sharp eyes see any bug or serious problem with it.

...
>---------------------------------------------------------cut here
#include <string.h>
#include <stdlib.h>
/*
The strndup function copies not more than n characters (characters that
follow a null character are not copied) from string to a dynamically
allocated buffer. The copied string shall always be null terminated.
*/
char *strndup(const char *string,size_t s)


I haven't looked at the code, but I am a big believer in accurate
documentation.

Your comment references "n characters", but defines a parameter s. Is
that n? The comment doesn't say how many characters are copied, only
that it is not more than n, so I can't rely on the function to copy the
full strlen(string), even if s exceeds this. I suggest calling the
result a dynamically allocated char array, rather than a buffer, since
it isn't necessarily buffering anything. As a matter of fact, since it
is presumably sized to the input string, there probably isn't room for
additional characters to be added later, thus not used as a buffer.

The description doesn't say what the results are if insufficient memory
exists for the new array.
Excuse me I just cutted and pasted the specification from the
standards document. It is not my documentation.
Dec 3 '06 #11
CBFalconer a écrit :
Tom St Denis wrote:
char *strndup(const char *_string, size_t _len) {
char *s, *p;

if ((p = s = malloc(_len + 1)))
Here you allocate _len characters even if the string could be
considerably shorter... This wastes space.
Dec 3 '06 #12
On Sat, 02 Dec 2006 23:53:26 +0100, jacob navia wrote:
>Reading comp.std.c
....
>It proposes really interesting functions, among others getline and
getdelim, that I introduced into lcc-win32 (by coincidence) a few weeks
ago.
It proposes strdup and strndup too. Lcc-win32 proposes already strdup,
but strndup was missing.
strdup, getline and other functions require deallocation by the user.
They were deliberately excluded from the C Standards. Not by
oversight, not because they were difficult to implement, not because
they wouldn't have been 'useful'.

Best regards,
Roland Pibinger
Dec 3 '06 #13
Roland Pibinger a écrit :
On Sat, 02 Dec 2006 23:53:26 +0100, jacob navia wrote:
>>Reading comp.std.c

...
>>It proposes really interesting functions, among others getline and
getdelim, that I introduced into lcc-win32 (by coincidence) a few weeks
ago.
It proposes strdup and strndup too. Lcc-win32 proposes already strdup,
but strndup was missing.


strdup, getline and other functions require deallocation by the user.
They were deliberately excluded from the C Standards. Not by
oversight, not because they were difficult to implement, not because
they wouldn't have been 'useful'.

Best regards,
Roland Pibinger
1) What's wrong with the user deallocating?
2) Maybe this view is changing since that technical report is there...
Dec 3 '06 #14
jacob navia said:
CBFalconer a écrit :
>BTW, Jacobs code carelessly fails to define size_t.
(Wrong, Chuck!)
>
???
I have
#include <stdlib.h>
and that file includes stddef.h that defines size_t
On your particular implementation, possibly, but the Standard doesn't
require this as far as I know. What it *does* require is that size_t is
available as a type to those translation units that have included
<stdlib.h>. So yes, your code was correct in that regard.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 3 '06 #15
Richard Heathfield a écrit :
jacob navia said:

>>CBFalconer a écrit :
>>>BTW, Jacobs code carelessly fails to define size_t.


(Wrong, Chuck!)

>>???
I have
#include <stdlib.h>
and that file includes stddef.h that defines size_t


On your particular implementation, possibly, but the Standard doesn't
require this as far as I know. What it *does* require is that size_t is
available as a type to those translation units that have included
<stdlib.h>. So yes, your code was correct in that regard.
stdlib.h defines

calloc(size_t,s ize_t)
malloc(size_t)
qsort(void *,size_t,size_t ,int (*)(...etc));
realloc(size_t) ;

and many others, so I do not see how size_t could be unknown after
including stdlib.h...

Obviously in other implementation they could have defined size_t
several times in several files.
Dec 3 '06 #16
jacob navia said:

<snip>
>
stdlib.h defines

calloc(size_t,s ize_t)
malloc(size_t)
qsort(void *,size_t,size_t ,int (*)(...etc));
realloc(size_t) ;

and many others, so I do not see how size_t could be unknown after
including stdlib.h...
True enough - or, better still, we can simply quote chapter and verse at
Chuck:

"4.10 GENERAL UTILITIES <stdlib.h>

The header <stdlib.hdeclar es four types and several functions of
general utility, and defines several macros./113/

The types declared are size_t and wchar_t (both described in $4.1.5),..."

<snip>

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 3 '06 #17
jacob navia wrote:
CBFalconer a écrit :
>char *strndup(const char *_string, size_t _len) {
char *s, *p;

if ((p = s = malloc(_len + 1)))

Here you allocate _len characters even if the string could be
considerably shorter... This wastes space.
The only possible use for the function is to truncate input
strings, as I pointed out. In that case there is no space wasted.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net>
Dec 3 '06 #18
Roland Pibinger wrote:
On Sat, 02 Dec 2006 23:53:26 +0100, jacob navia wrote:
>Reading comp.std.c
...
>It proposes really interesting functions, among others getline and
getdelim, that I introduced into lcc-win32 (by coincidence) a few
weeks ago.
It proposes strdup and strndup too. Lcc-win32 proposes already
strdup, but strndup was missing.

strdup, getline and other functions require deallocation by the user.
They were deliberately excluded from the C Standards. Not by
oversight, not because they were difficult to implement, not because
they wouldn't have been 'useful'.
By that reasoning malloc, calloc, and realloc should also be
omitted. Not to mention fopen.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net>
Dec 3 '06 #19
jacob navia wrote:
CBFalconer a écrit :
>BTW, Jacobs code carelessly fails to define size_t.

???
I have
#include <stdlib.h>
and that file includes stddef.h that defines size_t
Sorry, you are right there. However there is no requirement that
stdlib includes stddef, only that it define size_t (among other
things).
>It also return NULL for other reasons than lack of memory, which
can only cause confusion.
??? Why confusion?

Null means failure
Because the caller can't tell whether or not the system is out of
memory. If you are going to define the 'undefined behaviour' from
calling with an invalid parameter, you might as well make it
something innocuous. Otherwise the only way the user can tell the
cause of the error is to save the input parameter, and test it for
NULL himself after the routine returns a NULL. If he does that he
might as well test first, and not call the routine.

The other basic choice is to let a bad parameter blow up in the
function. Both will work properly if the programmer tests and
avoids passing that bad parameter in the first place. If he
doesn't the 'innocuous behavior' has a much better chance of
producing a user friendly end application. The unsophisticated end
user has little use for a segfault message.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net>
Dec 3 '06 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.