473,779 Members | 2,072 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
Richard Heathfield wrote:
>
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>
We can, but I also use jacob navia's logic
to deduce what's defined in a header,
except for stddef.h which is small enough to learn.

I tend to be more familiar with standard function descriptions
from looking them up repeatedly,
than I am with the standard header descriptions in their entirety.

I know that the ctype functions are described as being
able to take the value of EOF as an argument,
so I know that EOF is defined in ctype.h.

I know that putchar is described as being
able to return the value of EOF,
so I know that EOF is defined in stdio.h.

--
pete
Dec 3 '06 #21
jacob navia wrote:
[ 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...

Obviously in other implementation they could have defined size_t
several times in several files.
Lazy? Headers tend to declare rather than define. All four of your
examples fail as prototypes.

realloc's prototype..

void *realloc(void *_ptr, size_t _size);

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Dec 3 '06 #22
Joe Wright a écrit :
jacob navia wrote:
[ snip ]
>stdlib.h defines

calloc(size_t, size_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.


Lazy? Headers tend to declare rather than define. All four of your
examples fail as prototypes.

realloc's prototype..

void *realloc(void *_ptr, size_t _size);
Please Joe do not use my mail messages as header files :-)

I was just copying, and I wrote (etc...) sometimes to
speed it up. Maybe is lazyness but I just wanted to make a point,
not to write a header file.
Dec 3 '06 #23
[comp.compilers. lcc snipped as there is nothing lcc-specific here]

In article <45************ ***@yahoo.com>
CBFalconer <cb********@mai neline.netwrote :
>... However there is no requirement that
stdlib includes stddef, only that it define size_t (among other
things).
Indeed, in fact including <stdlib.hmust *not* include <stddef.h>,
because stddef.h will (e.g.) define "offsetof", and it must not be
defined if you have included only stdlib.h:

% cat x.c
#include <stdlib.h>
#ifdef offsetof
# error offsetof defined when it should not be
#endif
void f(void){}
%

This x.c translation unit must translate without error, i.e., the
#error must not fire.

(Now that it has been officially announced I can mention this: One
rather painful aspect of obtaining POSIX PSE52 certification for
vxWorks 6.4 was cleaning up our header-file organization so that
"inappropri ate" symbols were not defined by including various POSIX
headers. The certification process includes code that reads the
actual headers, searching for all things that look like identifiers,
and emits a test module to make sure they are not "#define"d when
compiling in "POSIX mode". Only names reserved to the implementor
-- things like __users_must_no t_use_this_iden tifier -- are omitted
from this test.

Making header files "do the right thing" when writing them from
scratch is not that bad, but retroactively enforcing such rules in
a system with many years of history is more difficult.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Dec 3 '06 #24
On Sun, 03 Dec 2006 12:49:37 +0100, jacob navia wrote:
>1) What's wrong with the user deallocating?
It's bad style. The responsibility for deallocation becomes unclear.
In your program you have some functions that return a char* that must
be freed and other functions retruning char* without that requirement:
a perfect receipt for a leaking program.
Moreover, functions like getline foster an inefficient style. They
dynamically allocate memory for each line even when most of the lines
would fit into a char[80] buffer and only exceptional cases needed
dynamic allocation.
>2) Maybe this view is changing since that technical report is there...
Why should they abandon good style?

Best regards,
Roland Pibinger
Dec 3 '06 #25
On Sun, 03 Dec 2006 10:01:01 -0500, CBFalconer wrote:
>By that reasoning malloc, calloc, and realloc should also be
omitted.
Why? Do those functions force you to free something you haven't
allocated?
>Not to mention fopen.
Wrong analogy again. Would you write a function like the following
(probably not):

/* user must call fclose() on the returned FILE* */
FILE *do_something (int i);

Best regards,
Roland Pibinger
Dec 3 '06 #26
Roland Pibinger a écrit :
On Sun, 03 Dec 2006 12:49:37 +0100, jacob navia wrote:
>>1) What's wrong with the user deallocating?


It's bad style. The responsibility for deallocation becomes unclear.
In your program you have some functions that return a char* that must
be freed and other functions retruning char* without that requirement:
a perfect receipt for a leaking program.
Moreover, functions like getline foster an inefficient style. They
dynamically allocate memory for each line even when most of the lines
would fit into a char[80] buffer and only exceptional cases needed
dynamic allocation.

>>2) Maybe this view is changing since that technical report is there...


Why should they abandon good style?

Best regards,
Roland Pibinger
The responsability of the deallocation is perfectly clear: the specs
specify that the user should deallocate the new space.

And to the argument that this is inefficient, just pass a buffer
(allocated with malloc) to this function. It will NOT touch the
passed buffer unless IT NEEEDS TO!!!

If all your lines are less than 80 characters and you pass it
a buffer of 80, the buffer will be reused!
Dec 3 '06 #27
jacob navia wrote:
Thad Smith a écrit :
>jacob navia wrote:
>> Here is a proposed implementation. I would like
to see if your sharp eyes see any bug or serious problem with it.
....
>>/*
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
documentatio n.
[suggestions to improve function description deleted]
>
Excuse me I just cutted and pasted the specification from the
standards document. It is not my documentation.
Feel free to forward my comments to the author. Still, if you
distribute such a function, I recommend you use a better description.

--
Thad
Dec 3 '06 #28
"Roland Pibinger" <rp*****@yahoo. comwrote in message
news:45******** ******@news.uta net.at...
On Sun, 03 Dec 2006 10:01:01 -0500, CBFalconer wrote:
>>Not to mention fopen.

Wrong analogy again. Would you write a function like the following
(probably not):

/* user must call fclose() on the returned FILE* */
FILE *do_something (int i);
I've written code like that, yes, though more often with <OT>open() /
close()</OTthan fopen() / fclose(). It's also pretty standard when
working with <OT>sockets</OT>; because they require so much f'ing work
to create, people tend to put all that in another function to avoid
clutter.

This whole "who deallocates the returned string" argument is one of the
largest problems I have with C; yes, you can always find the correct
answer if you look at the function specs (assuming they exist), but it's
not obvious and is therefore prone to errors. <OTI'm often tempted to
use the C-like subset of C++ just so I'll have string objects that
deallocate (er, destruct) themselves when appropriate rather than having
to read function specs to figure things out. The hassle of requiring a
working C++ environment isn't yet worth the gain, though it's getting
closer. </OT>

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking
--
Posted via a free Usenet account from http://www.teranews.com

Dec 3 '06 #29
Joe Wright <jo********@com cast.netwrites:
jacob navia wrote:
[ snip ]
>stdlib.h defines
calloc(size_t, size_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.

Lazy? Headers tend to declare rather than define. All four of your
examples fail as prototypes.
How so? A prototype is a function declaration that declares the types
(not necessarily the names) of its parameters. Only the definition
needs the parameter names.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 3 '06 #30

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.