473,503 Members | 7,823 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

strdup()

As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?

<OT>Is it in POSIX perhaps?</OT>
Nov 14 '05 #1
32 6328
Grumble <de*****@kma.eu.org> writes:
As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?
Yes.
<OT>Is it in POSIX perhaps?</OT>


I believe so.

--
Keith Thompson (The_Other_Keith) 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.
Nov 14 '05 #2
On Tue, 22 Mar 2005 10:37:25 +0100, Grumble
<de*****@kma.eu.org> wrote:
As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?
Correct. It's trivial to implement, though:

#include <stdlib.h>
char *strdup(const char *str)
{
char *cpy = NULL;
if (str)
{
cpy = malloc(strlen(str)+1);
if (cpy)
strcpy(cpy, str);
}
return cpy;
}

(Actually, POSIX doesn't specify what happens if a null pointer is
passed in, but I prefer the trivial test so that strdup(NULL) == NULL.)
<OT>Is it in POSIX perhaps?</OT>


It is. Some useful URLs for POSIX:

http://www.opengroup.org/onlinepubs/...9/nfindex.html
http://www.opengroup.org/onlinepubs/007908799/toc.htm
http://www.everything2.com/?node=Posix

Chris C
Nov 14 '05 #3
"Grumble" <de*****@kma.eu.org> wrote in message
As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?
sure
<OT>Is it in POSIX perhaps?</OT>


strdup() was manditory in UNIX 95.

http://www.unix.org/

--
Tor <torust AT online DOT no>

Nov 14 '05 #4
Grumble wrote:
As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?

<OT>Is it in POSIX perhaps?</OT>


Here are my replacements for strdup (specified in POSIX) and
strndup (an extension from GNU libc).

/*
dupstr() and dupstrn(): Replacements for strdup() and strndup()

Written in 2004 by Robert Bachmann <rbach [AT] rbach.priv.at>
Public domain.
*/

#include <assert.h>
#include <stdlib.h>
#include <string.h>

/*
char* dupstr (const char *s)

Returns a pointer to a new string
which is a duplicate of the string s,
or NULL if malloc() failed.
*/
char* dupstr (const char *s)
{
char *p;
size_t n;

assert(s != NULL);

n=strlen(s) + 1;
p = malloc(n);

if (p)
p=memcpy(p,s,n);

return p;
}

/*
char* dupnstr (const char *s,size_t n)

Works like dupstr() but it only copies the
first n characters.
A terminating '\0' is *always* added.
*/
char* dupnstr (const char *s,size_t n)
{
char *p;

assert(s != NULL);

p = malloc(n+1);

if (p) {
p=strncpy(p,s,n);
p[n]='\0';
}
return p;
}

--
Robert Bachmann <ne**@rbach.priv.at>, PGP-KeyID: 0x8994A748
Nov 14 '05 #5
Robert Bachmann wrote:
.... snip ...
Here are my replacements for strdup (specified in POSIX) and
strndup (an extension from GNU libc).

/*
dupstr() and dupstrn(): Replacements for strdup() and strndup()

Written in 2004 by Robert Bachmann <rbach [AT] rbach.priv.at>
Public domain.
*/

#include <assert.h>
#include <stdlib.h>
#include <string.h>

/*
char* dupstr (const char *s)

Returns a pointer to a new string
which is a duplicate of the string s,
or NULL if malloc() failed.
*/
char* dupstr (const char *s)
{
char *p;
size_t n;

assert(s != NULL);

n=strlen(s) + 1;
p = malloc(n);

if (p)
p=memcpy(p,s,n);

return p;
}

/*
char* dupnstr (const char *s,size_t n)

Works like dupstr() but it only copies the
first n characters.
A terminating '\0' is *always* added.
*/
char* dupnstr (const char *s,size_t n)
{
char *p;

assert(s != NULL);

p = malloc(n+1);

if (p) {
p=strncpy(p,s,n);
p[n]='\0';
}
return p;
}


Try this modification (untested) which does reasonable things with
NULL input and eliminates the assert.

#include <stdlib.h>
#include <string.h>

char *dupstr(const char *s)
{
char *p;
size_t n;

if (!s || !(p = malloc(n = 1 + strlen(s))) return NULL;
else return memcpy(p, s, n);
}

and dupnstr is probably better built out of strlcpy from the BSD
world, an implementation of which is available on my site
<http://cbfalconer.home.att.net/download/>. There is no need to
insert those possibly very length strings of zeroes.

--
"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare
Nov 14 '05 #6
In article <42***************@yahoo.com>, CBFalconer wrote:
Robert Bachmann wrote:

#include <assert.h>
#include <stdlib.h>
#include <string.h>

/*
char* dupstr (const char *s)

Returns a pointer to a new string
which is a duplicate of the string s,
or NULL if malloc() failed.
*/
char* dupstr (const char *s)
{
char *p;
size_t n;

assert(s != NULL);

n=strlen(s) + 1;
p = malloc(n);

if (p)
p=memcpy(p,s,n);

return p;
}

[...]

Try this modification (untested) which does reasonable things with
NULL input and eliminates the assert.

#include <stdlib.h>
#include <string.h>

char *dupstr(const char *s)
{
char *p;
size_t n;

if (!s || !(p = malloc(n = 1 + strlen(s))) return NULL;
else return memcpy(p, s, n);
}


I would argue that your version is inferior because it masks the bug of
passing a null pointer to dupstr(), and there is no convenient way to
distinguish between this bug and failure to allocate memory. How is the
caller supposed to put your check to good use? Although the standard
does not say anything about errno being set to an appropriate error code
when malloc() fails, the ``Quality of Implementation'' factor is usually
such that malloc() does this. Therefore, callers of this function may
reasonably wish to rely on a meaningful errno value in order to diagnose
the error as ``dupstr() failed becaue of ...'' rather than ``dupstr()
failed for an unknown reason'':

char *p = dupstr(str);
if (p == NULL) {
perror("dupstr failed");
/* handle error */
}

If you really wish to keep the null pointer check, it is more useful to
set errno accordingly;

if (s == NULL) {
errno = EINVAL;
return NULL;
} else if ((p = malloc(n = strlen(s) + 1)) == NULL) {
return NULL;
}

(Of course, this decreases portability for no good reason because EINVAL
is not standard so it is not a very good solution either.)

--
My real email address is ``nils<at>gnulinux<dot>nl''
Nov 14 '05 #7
"Nils Weller" <me@privacy.net> wrote in message

<snip>
char *p = dupstr(str);
if (p == NULL) {
perror("dupstr failed");
/* handle error */
}

If you really wish to keep the null pointer check, it is more useful to set errno accordingly;

if (s == NULL) {
errno = EINVAL;
return NULL;
} else if ((p = malloc(n = strlen(s) + 1)) == NULL) {
return NULL;
}

Normally, a "mean and lean" attitude is sufficient. Why keep
on going -- if there isn't going to be done any recovery of
malloc failures anyway?

/* Warning: untested code follows ...*/
/* xmalloc: exit on failure */
void *xmalloc(size_t size)
{
void *mem;

/* pre-condition catch implementation defined behavoir */
assert (size > 0);

mem = malloc(size);
if (mem == NULL)
{
perror("xmalloc: Out of memory");
exit(EXIT_FAILURE);
}

return mem;
}

then our "strdup" can simply be written

/* xstrdup: exit on failure, never return NULL */
char *xstrdup(const char *str)
{
char *mem;

/* pre-condition catch UB */
assert(str != NULL);

mem = xmalloc(strlen(str) + 1);

/* post-condition */
assert(mem != NULL);

return strcpy(mem, str);
}

This simplify coding, since a lot if tests for NULL can be removed.
However, for a non-stop server, more advanced mem handling
is wanted, perhaps even using a GC.

--
Tor <torust AT online DOT no>

Nov 14 '05 #8
Tor Rustad wrote:
Normally, a "mean and lean" attitude is sufficient. Why keep
on going -- if there isn't going to be done any recovery of
malloc failures anyway?


Oh my.
Nov 14 '05 #9
>Normally, a "mean and lean" attitude is sufficient. Why keep
on going -- if there isn't going to be done any recovery of
malloc failures anyway?


I hope you don't design airplanes, nuclear power plants,
weapons systems, or firmware for automobile engines :-)

Gordon L. Burditt
Nov 14 '05 #10
In article <yi******************@news2.e.nsc.no>, Tor Rustad wrote:
"Nils Weller" <me@privacy.net> wrote in message

<snip>
char *p = dupstr(str);
if (p == NULL) {
perror("dupstr failed");
/* handle error */
}

If you really wish to keep the null pointer check, it is more useful

to
set errno accordingly;

if (s == NULL) {
errno = EINVAL;
return NULL;
} else if ((p = malloc(n = strlen(s) + 1)) == NULL) {
return NULL;
}

Normally, a "mean and lean" attitude is sufficient. Why keep
on going -- if there isn't going to be done any recovery of
malloc failures anyway?


The original poster explicitly mentioned that the code is intended to
act as a replacement for the UNIX function strdup(), and this function
is defined to return a null pointer if it failed to allocate any memory.

For the record: I agree that simply exiting is usually simpler than
trying to recover from an out-of-memory condition, and in fact I usually
use wrapper functions for malloc() and realloc() much like those you
posted.

--
My real email address is ``nils<at>gnulinux<dot>nl''
Nov 14 '05 #11
"Gordon Burditt" <go***********@burditt.org> wrote in message

Normally, a "mean and lean" attitude is sufficient. Why keep
on going -- if there isn't going to be done any recovery of
malloc failures anyway?


I hope you don't design airplanes, nuclear power plants,
weapons systems, or firmware for automobile engines :-)


Have done safety-critical engineering for many years, still do. :-)

Rule 118 (required):
"Dynamic heap memory allocation shall not be used"
Reference: MISRA C, April 1998

My point was, without any error-recovery logic elsewhere,
then it's simpler to die at the point-of-failure.

--
Tor <torust AT online DOT no>

Nov 14 '05 #12

Tor Rustad wrote:
My point was, without any error-recovery logic elsewhere,
then it's simpler to die at the point-of-failure.

I disagree. This is intended to be a library function, so it should not
be killing the application. The fact that the code as currently written
doesn't have error-checking does not justify removing any possibility
of doing so.


Brian

Nov 14 '05 #13

In article <42**********************@newsreader01.highway.tel ekom.at>, Robert Bachmann <ne**@rbach.priv.at> writes:

/*
char* dupnstr (const char *s,size_t n)

Works like dupstr() but it only copies the
first n characters.
A terminating '\0' is *always* added.
*/
char* dupnstr (const char *s,size_t n)
{
char *p;

assert(s != NULL);

p = malloc(n+1);

if (p) {
p=strncpy(p,s,n);
p[n]='\0';
}
return p;
}


IMO, this is infelicitous. If n > strlen(s), you're wasting memory
and cycles and possibly hurting locality of reference as well, due
to the unfortunate semantics of strncpy. If the intent of the
function is to always allocate n+1 bytes, fine, but that's not what
the description says.

If I were writing such a function I'd have it allocate the smaller
of n and strlen(s), plus 1.

Of course, this also falls afoul of Richard Heathfield's objection to
strncpy / strncat: it's only useful if you don't mind silently
truncating the copy. If you need to know whether truncation
occurred, you might as well just check the source length first. And
most well-behaved programs will need to know whether truncation
occurred (or would occur).

(On a similar note, I dislike assert; my functions do parameter
sanity checking, but they return errors if they fail. They don't
take the whole program down. And yes, I know this is a religious
issue for some and we've been over it more than once here.)

--
Michael Wojcik mi************@microfocus.com

Pseudoscientific Nonsense Quote o' the Day:
From the scientific standpoint, until these energies are directly
sensed by the evolving perceptions of the individual, via the right
brain, inner-conscious, intuitive faculties, scientists will never
grasp the true workings of the universe's ubiquitous computer system.
-- Noel Huntley
Nov 14 '05 #14
Nils Weller wrote:
CBFalconer wrote:

.... snip ...

Try this modification (untested) which does reasonable things with
NULL input and eliminates the assert.

#include <stdlib.h>
#include <string.h>

char *dupstr(const char *s)
{
char *p;
size_t n;

if (!s || !(p = malloc(n = 1 + strlen(s))) return NULL;
else return memcpy(p, s, n);
}


I would argue that your version is inferior because it masks the bug of
passing a null pointer to dupstr(), and there is no convenient way to
distinguish between this bug and failure to allocate memory. How is the
caller supposed to put your check to good use? Although the standard
does not say anything about errno being set to an appropriate error code
when malloc() fails, the ``Quality of Implementation'' factor is usually
such that malloc() does this. Therefore, callers of this function may
reasonably wish to rely on a meaningful errno value in order to diagnose
the error as ``dupstr() failed becaue of ...'' rather than ``dupstr()
failed for an unknown reason'':


Ah, but I document my dupstr/strdup as accepting NULL and returning
NULL for NULL. :-)

If the user really wants to guard against original NULLs he should
be writing (regardless of the dupstr version):

if (!s1) {
/* We have an original NULL case */
}
else if (!(s2 = dupstr(s1))) {
/* we have detected mem failure */;
}
else {
/* carry on Jack */
}

My attitude means that one can make a deep copy of a string as long
as the pointer content is valid. I can see more uses for that than
for crashing on NULL. For example:

char *table[SOMESZ];
char *auxtbl[SOMESZ];
size_t i;

....
/* code filling table with pointers or NULLs everywhere */
....
/* deep copy of table needed, high confidence in malloc */
for (i = 0; i < SOMESZ; i++) auxtbl[i] = dupstr(table[i]);

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #15

"Default User" <de***********@yahoo.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...

Tor Rustad wrote:
My point was, without any error-recovery logic elsewhere,
then it's simpler to die at the point-of-failure.

I disagree. This is intended to be a library function, so it should

not be killing the application. The fact that the code as currently written doesn't have error-checking does not justify removing any possibility
of doing so.


Well, nothing is stopping you from calling malloc(), I argue only that
xmalloc() is a better alternative in many cases, but not for _all_.

However, a better design for a library error handling, is to provide
a mechanism for a callback function, than to return NULL pointers
and to have if-checks all over the place.

--
Tor <torust AT online DOT no>

Nov 14 '05 #16
Michael Wojcik wrote:
IMO, this is infelicitous. If n > strlen(s), you're wasting memory
and cycles [...]
If the intent of the
function is to always allocate n+1 bytes, fine, but that's not what
the description says.
I agree my dupnstr could be a big memory waster if the strings passed
to it are shorter than n, but my description of dupnstr never said that
dupnstr will only allocate n+1 bytes.

However, here are two alternative implementations of dupnstr.

char* alt1_dupnstr (const char *s, size_t n)
{
char *p;
const char *org;
size_t len=0;

assert(s != NULL);

if (n==0)
return calloc(1,1);

org=s;
while(n-- && *s++)
++len;

p=malloc(len+1);

if (p) {
(void) memcpy(p,org,len);
p[len]='\0';
}

return p;
}

char* alt2_dupnstr (const char *s,size_t n)
{
char *p;
size_t len=0;

assert(s != NULL);

if (n==0)
return calloc(1,1);

p=malloc(n+1);

if (p)
{
char *op=p;

while(n && (*p++ = *s++) )
{
++len;
--n;
}

if (n==0)
{
*p='\0';
p=op;
}
else
{
p = realloc(op,len+1);
if (p == NULL)
free(op);
}
}

return p;
}
Of course, this also falls afoul of Richard Heathfield's objection to
strncpy / strncat: it's only useful if you don't mind silently
truncating the copy. If you need to know whether truncation
occurred, you might as well just check the source length first. And
most well-behaved programs will need to know whether truncation
occurred (or would occur).

I'm not the inventor of strndup, I only tried to provide a portable
PD alternative.

--
Robert Bachmann <ne**@rbach.priv.at>, PGP-Key ID: 0x8994A748
Nov 14 '05 #17
"Tor Rustad" <to****@online.no.spam> wrote:
"Gordon Burditt" <go***********@burditt.org> wrote in message

Normally, a "mean and lean" attitude is sufficient. Why keep
on going -- if there isn't going to be done any recovery of
malloc failures anyway?
I hope you don't design airplanes, nuclear power plants,
weapons systems, or firmware for automobile engines :-)


Have done safety-critical engineering for many years, still do. :-)

Rule 118 (required):
"Dynamic heap memory allocation shall not be used"
Reference: MISRA C, April 1998


Whoever wrote this rule does not understand the perversity of human
nature. What's to stop me from declaring a humungous static array, and
getting my dynamic memory from it? Well-checked dynamic allocation is
perfectly safe; this rule should read more like "All dynamic memory
allocation shall be checked, and appropriate measures taken on failure".
Note also the absence of the word "heap".
My point was, without any error-recovery logic elsewhere,
then it's simpler to die at the point-of-failure.


That's not an argument for dying in a malloc() wrapper, that's an
argument for more error recovery elsewhere.

Richard
Nov 14 '05 #18
On Fri, 25 Mar 2005 10:48:29 GMT, rl*@hoekstra-uitgeverij.nl (Richard
Bos) wrote:
"Tor Rustad" <to****@online.no.spam> wrote:
"Gordon Burditt" <go***********@burditt.org> wrote in message
> >
> >Normally, a "mean and lean" attitude is sufficient. Why keep
> >on going -- if there isn't going to be done any recovery of
> >malloc failures anyway?
>
> I hope you don't design airplanes, nuclear power plants,
> weapons systems, or firmware for automobile engines :-)
Have done safety-critical engineering for many years, still do. :-)

Rule 118 (required):
"Dynamic heap memory allocation shall not be used"
Reference: MISRA C, April 1998


Whoever wrote this rule does not understand the perversity of human
nature. What's to stop me from declaring a humungous static array, and
getting my dynamic memory from it? Well-checked dynamic allocation is
perfectly safe; this rule should read more like "All dynamic memory
allocation shall be checked, and appropriate measures taken on failure".
Note also the absence of the word "heap".


Your point about perversity is well taken, but your replacement is
not. To preserve the intent the text should be "Dynamic memory
allocation shall not be used." Putting in the word "heap" allows a
bit of weaseling. The general issue is that in safety-critical
software resource requirements should be determinable in advance.
My point was, without any error-recovery logic elsewhere,
then it's simpler to die at the point-of-failure.


That's not an argument for dying in a malloc() wrapper, that's an
argument for more error recovery elsewhere.

Richard


Richard Harter, cr*@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
All my life I wanted to be someone;
I guess I should have been more specific.
Nov 14 '05 #19
On Fri, 25 Mar 2005 10:48:29 GMT, Richard Bos
<rl*@hoekstra-uitgeverij.nl> wrote:
"Tor Rustad" <to****@online.no.spam> wrote:
Have done safety-critical engineering for many years, still do. :-)

Rule 118 (required):
"Dynamic heap memory allocation shall not be used"
Reference: MISRA C, April 1998
Whoever wrote this rule does not understand the perversity of human
nature. What's to stop me from declaring a humungous static array, and
getting my dynamic memory from it?


Nothing, whatever you do with your memory is your problem. If you
choose to write buggy code you may well get fired, of course...

The point of that rule -- and although I've never worked under MISRA
rules I've worked on a number of projects with something similar -- is
to ensure that nothing your code does with memory will affect any other
code inadvertently (for instance by causing it to run out of memory).
The total memory requirements of the system are known at build time, and
include things like tasks/threads created statically and stacks with
maximum sizes.
Well-checked dynamic allocation is
perfectly safe; this rule should read more like "All dynamic memory
allocation shall be checked, and appropriate measures taken on failure".
Note also the absence of the word "heap".


If it does run out unexpectedly then very often in a real-time system
nothing can be done except die (and in a safety-critical system that
'die' may well be literal on the part of the user), it can't wait around
to see if memory gets freed later. Hence "no dynamic memory", every
task knows exactly how much memory is available to it.
My point was, without any error-recovery logic elsewhere,
then it's simpler to die at the point-of-failure.


That's not an argument for dying in a malloc() wrapper, that's an
argument for more error recovery elsewhere.


Like what? If I've allocated the memory I need, and then need some more
and it isn't there, what am I supposed to do? I can't assume that some
more might become available if I wait, that could lock it up for ever.
Dying in a wrapper (which can of course call cleanup to close files
etc., although that could fail as well if we're out of memory, and can
display or log the information) is often the only sensible thing to do.
Why do the same 'recovery' all over the place when it can be done in one
place, and that place can be easily altered to do things like logging
the fault, or providing a place to put a debugging breakpoint.

Chris C
Nov 14 '05 #20
Groovy hepcat Chris Croughton was jivin' on Tue, 22 Mar 2005 11:55:03
+0000 in comp.lang.c.
Re: strdup()'s a cool scene! Dig it!
On Tue, 22 Mar 2005 10:37:25 +0100, Grumble
<de*****@kma.eu.org> wrote:
As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?


Correct. It's trivial to implement, though:


Yes, if you want to have nasal demons for tea. Identifiers with
external linkage beginning with str and a lower case letter are
reserved.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
Nov 14 '05 #21
Peter Shaggy Haywood wrote:
Groovy hepcat Chris Croughton was jivin' on Tue, 22 Mar 2005 11:55:03
+0000 in comp.lang.c.
Re: strdup()'s a cool scene! Dig it!

On Tue, 22 Mar 2005 10:37:25 +0100, Grumble
<de*****@kma.eu.org> wrote:

As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?


Correct. It's trivial to implement, though:

Yes, if you want to have nasal demons for tea. Identifiers with
external linkage beginning with str and a lower case letter are
reserved.


Oh Peter, you're such an old woman. Surely defining strdup() will get
you in trouble only if it already exists, in which case you don't need
to define it yourself. :-)
--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #22
Mac
On Sat, 26 Mar 2005 09:35:18 -0500, Joe Wright wrote:
Peter Shaggy Haywood wrote:
Groovy hepcat Chris Croughton was jivin' on Tue, 22 Mar 2005 11:55:03
+0000 in comp.lang.c.
Re: strdup()'s a cool scene! Dig it!

On Tue, 22 Mar 2005 10:37:25 +0100, Grumble
<de*****@kma.eu.org> wrote:
As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?

Correct. It's trivial to implement, though:

Yes, if you want to have nasal demons for tea. Identifiers with
external linkage beginning with str and a lower case letter are
reserved.


Oh Peter, you're such an old woman. Surely defining strdup() will get
you in trouble only if it already exists, in which case you don't need
to define it yourself. :-)


Unless the already existing version uses a different interface, which it
could, since it is not a standard function.

--Mac

Nov 14 '05 #23
On Sat, 26 Mar 2005 09:35:18 -0500, in comp.lang.c , Joe Wright
<jo********@comcast.net> wrote:
Peter Shaggy Haywood wrote:

Yes, if you want to have nasal demons for tea. Identifiers with
external linkage beginning with str and a lower case letter are
reserved.

Oh Peter, you're such an old woman. Surely defining strdup() will get
you in trouble only if it already exists, in which case you don't need
to define it yourself. :-)


.... except that its forbidden by the language specification, so your
compiler is entitled to get sniffy with you...

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #24
On Sun, 27 Mar 2005 00:41:06 GMT, Peter "Shaggy" Haywood
<ph******@alphalink.com.au.NO.SPAM> wrote:
Groovy hepcat Chris Croughton was jivin' on Tue, 22 Mar 2005 11:55:03
+0000 in comp.lang.c.
Re: strdup()'s a cool scene! Dig it!
On Tue, 22 Mar 2005 10:37:25 +0100, Grumble
<de*****@kma.eu.org> wrote:
As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?


Correct. It's trivial to implement, though:


Yes, if you want to have nasal demons for tea. Identifiers with
external linkage beginning with str and a lower case letter are
reserved.


If it's already defined, you don't need to define it! On any POSIX
compliant system it will be defined anyway, so all you need to do when
porting is to determine whether the new system has it and if not enable
your own version. My applications do that automatically when
configuring for a new installation, because in practice real world
applications need access to many non-standard things (the C spec.
doesn't know anything about file systems and directories, for example,
but real users need that access), strdup is just one of many things
which might be there and if not need to be replaced.

In practice, any new functions in a future standard will be compatible
(or at least not clash with) with other existing standards like POSIX,
because if they aren't they will cause breakage in too much code and
the new standard just won't be used and will fall into disrepute.

Chris C
Nov 14 '05 #25
Groovy hepcat Chris Croughton was jivin' on Sun, 27 Mar 2005 13:01:22
+0100 in comp.lang.c.
Re: strdup()'s a cool scene! Dig it!
On Sun, 27 Mar 2005 00:41:06 GMT, Peter "Shaggy" Haywood
<ph******@alphalink.com.au.NO.SPAM> wrote:
Groovy hepcat Chris Croughton was jivin' on Tue, 22 Mar 2005 11:55:03
+0000 in comp.lang.c.
Re: strdup()'s a cool scene! Dig it!
On Tue, 22 Mar 2005 10:37:25 +0100, Grumble
<de*****@kma.eu.org> wrote:

As far as I can tell, strdup() is neither in C89 nor in C99.

Is that correct?

Correct. It's trivial to implement, though:
Yes, if you want to have nasal demons for tea. Identifiers with
external linkage beginning with str and a lower case letter are
reserved.


If it's already defined, you don't need to define it! On any POSIX


So you want to write a different version of the code for each
implementation you compile it on? Well, if that's what floats your
boat then who am I to stifle you? But I prefer to write code that's
portable.
compliant system it will be defined anyway, so all you need to do when
porting is to determine whether the new system has it and if not enable
And what about all those implementations that are not POSIX
compliant but have extentions named strdup which may or may not follow
the usual idioms? You'd have to make special arrangements for them.
With a function as trivial as the one we're discussing here, it is so
much easier to just write it yourself portably than to do what you
suggest.
your own version. My applications do that automatically when
configuring for a new installation, because in practice real world
applications need access to many non-standard things (the C spec.
True. But why make the situation worse by invoking undefined
behaviour?
doesn't know anything about file systems and directories, for example,
but real users need that access), strdup is just one of many things
which might be there and if not need to be replaced.

In practice, any new functions in a future standard will be compatible
(or at least not clash with) with other existing standards like POSIX,
And what about all those implementations that don't follow existing
standards like POSIX? They often do things different just to be
difficult. You should take that into account when writing code.
because if they aren't they will cause breakage in too much code and
the new standard just won't be used and will fall into disrepute.


Oh, is that what'll happen, eh?

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
Nov 14 '05 #26
On Mon, 28 Mar 2005 18:05:44 GMT, Peter "Shaggy" Haywood
<ph******@alphalink.com.au.NO.SPAM> wrote:
Groovy hepcat Chris Croughton was jivin' on Sun, 27 Mar 2005 13:01:22
+0100 in comp.lang.c.
Re: strdup()'s a cool scene! Dig it!
On Sun, 27 Mar 2005 00:41:06 GMT, Peter "Shaggy" Haywood
<ph******@alphalink.com.au.NO.SPAM> wrote:
Groovy hepcat Chris Croughton was jivin' on Tue, 22 Mar 2005 11:55:03
+0000 in comp.lang.c.
Re: strdup()'s a cool scene! Dig it!

On Tue, 22 Mar 2005 10:37:25 +0100, Grumble
<de*****@kma.eu.org> wrote:

> As far as I can tell, strdup() is neither in C89 nor in C99.
>
> Is that correct?

Correct. It's trivial to implement, though:

Yes, if you want to have nasal demons for tea. Identifiers with
external linkage beginning with str and a lower case letter are
reserved.
If it's already defined, you don't need to define it! On any POSIX


So you want to write a different version of the code for each
implementation you compile it on? Well, if that's what floats your
boat then who am I to stifle you? But I prefer to write code that's
portable.


If you want to limit yourself to those few programs which are totally
portable (nothing which involves directory access, for a start), I'm
not stopping you. I need to write programs in the real world, however,
where it can't be guaranteed that even all of the C89 functions will be
implemented, so I need to provide replacements for them.

Since it's in my library of "things I find useful", the only 'porting' I
need to do is to determine whether it is available on the target
platform, and for most of them that will happen automatically. That
sort of thing needs to be done anyway to determine headers for doing
filesystem access (read directories), sockets, pipes, whether long long
exists, and many more non portable but essential features in real
programs.
compliant system it will be defined anyway, so all you need to do when
porting is to determine whether the new system has it and if not enable


And what about all those implementations that are not POSIX
compliant but have extentions named strdup which may or may not follow
the usual idioms? You'd have to make special arrangements for them.


What implementation has strdup() which does not follow the idiom? I
haven't found one in the last 20+ years, and I very much doubt that
anyone would be foolish enough to write one now.
With a function as trivial as the one we're discussing here, it is so
much easier to just write it yourself portably than to do what you
suggest.


Duh, I did just write it portably.
your own version. My applications do that automatically when
configuring for a new installation, because in practice real world
applications need access to many non-standard things (the C spec.


True. But why make the situation worse by invoking undefined
behaviour?


It is only 'undefined' by the C standard, which is not the only standard
in real world programs.
doesn't know anything about file systems and directories, for example,
but real users need that access), strdup is just one of many things
which might be there and if not need to be replaced.

In practice, any new functions in a future standard will be compatible
(or at least not clash with) with other existing standards like POSIX,


And what about all those implementations that don't follow existing
standards like POSIX? They often do things different just to be
difficult. You should take that into account when writing code.


Examples? As I said, I have never found any library implementations of
strdup() which do anything other than what the POSIX standard says (even
before POSIX existed). The worst is on K&R systems which didn't support
const, but that will blow most C89 and later programs anyway.
because if they aren't they will cause breakage in too much code and
the new standard just won't be used and will fall into disrepute.


Oh, is that what'll happen, eh?


Anything which breaks POSIX will just be ignored by the vast majority of
the programmers, because there is too much POSIX compliant code which
would be affected. Having standards which are ignored causes them to
fall into disrepute (this is happening anyway with C99, very few places
are at all interested in going to C99 compliant compilers), just as it
does with laws.

I just did a scan of some of the Free Software source on my system.
Every project there uses strdup(). Perl, Python, Qt, openSSL, fvwm,
gcc, procmail, GPG, Doxygen, all of the libraries, etc. (it's almost 100
directories, I'm not going to bother to list them all). I somehow think
that anyone re-using it as something different would not be popular...

Chris C
Nov 14 '05 #27
On Mon, 28 Mar 2005 12:42:32 +0100, Chris Croughton
<ch***@keristor.net> wrote:

If you want to limit yourself to those few programs which are totally
portable (nothing which involves directory access, for a start), I'm
not stopping you. I need to write programs in the real world, however,
where it can't be guaranteed that even all of the C89 functions will be
implemented, so I need to provide replacements for them.


I'm a little puzzled. Would your function stop working if you named it
"dupstr" instead of "strdup"?

You make a good (if obvious) case for writing functions of your own,
but no case for violating the implementation name space.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #28
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
"Tor Rustad" <to****@online.no.spam> wrote:
<snip>
Rule 118 (required):
"Dynamic heap memory allocation shall not be used"
Reference: MISRA C, April 1998


Whoever wrote this rule does not understand the perversity of human
nature. What's to stop me from declaring a humungous static array, and
getting my dynamic memory from it?


Whoever try to fool automated code checkers this way, will for sure
piss off the person doing the external code review! :-)

Well-checked dynamic allocation is
perfectly safe; this rule should read more like "All dynamic memory
allocation shall be checked, and appropriate measures taken on
failure".


Nope, *non-deterministic* memory usage, should of course
be avoided in safety-critical systems.

However, there might be cases where dynamic memory based
algorithms are far simpler to implement, i.e. a valid point then,
is that "the cure might be worse than the disease".
My point was, without any error-recovery logic elsewhere,
then it's simpler to die at the point-of-failure.


That's not an argument for dying in a malloc() wrapper, that's an
argument for more error recovery elsewhere.


What kind of malloc error recovery do you talk about?

If the system is out of resources, then there isn't that simple
to recover from it. Ignoring HW faults, either your program has
a bug _or_ your system need more memory to continue to run
the program (assuming no GC is in use).

I have written fault-tolerant servers that can do recovery from
malloc failures, but in many cases such fault-tolerant
programming is simply not needed.

--
Tor <torust AT online DOT no>

Nov 14 '05 #29
On Tue, 29 Mar 2005 21:39:23 +0200, in comp.lang.c , "Tor Rustad"
<to****@online.no.spam> wrote:
*non-deterministic* memory usage, should of course
be avoided in safety-critical systems.


non-deterministic? You mean you find yourself often allocating quantum
amounts of memory, or random amounts, or imaginary amounts, or amounts
at relativistic velocities? Wow....
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
Nov 14 '05 #30
Mark McIntyre <ma**********@spamcop.net> writes:
On Tue, 29 Mar 2005 21:39:23 +0200, in comp.lang.c , "Tor Rustad"
<to****@online.no.spam> wrote:
*non-deterministic* memory usage, should of course
be avoided in safety-critical systems.


non-deterministic? You mean you find yourself often allocating quantum
amounts of memory, or random amounts, or imaginary amounts, or amounts
at relativistic velocities? Wow....


Non-deterministic, in this context, probably means that the amount of
memory allocated may depend on input to the program.

A program that allocates exactly 42 fixed-size buffers during startup
has deterministic memory usage. One that allocates a fixed-size (or
variable-size) buffer each time some external event occurs has
non-deterministic memory usage.

In a text editor or a game it's acceptable to run some finite risk of
running out of memory (and possibly crashing) under unusual
circumstances. In a safety-critical system, it's often important to
prove rigorously that this can *never* happen (assuming reliable
hardware).

--
Keith Thompson (The_Other_Keith) 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.
Nov 14 '05 #31
"Tor Rustad" <to****@online.no.spam> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
"Tor Rustad" <to****@online.no.spam> wrote:

Rule 118 (required):
"Dynamic heap memory allocation shall not be used"
Reference: MISRA C, April 1998


Whoever wrote this rule does not understand the perversity of human
nature. What's to stop me from declaring a humungous static array, and
getting my dynamic memory from it?


Whoever try to fool automated code checkers this way, will for sure
piss off the person doing the external code review! :-)


I trusty the person doing the review better than a hard and fast rule.

Richard
Nov 14 '05 #32
Chris Croughton wrote:

On Mon, 28 Mar 2005 18:05:44 GMT, Peter "Shaggy" Haywood
<ph******@alphalink.com.au.NO.SPAM> wrote:

And what about all those implementations that don't follow
existing
standards like POSIX? They often do things different just to be
difficult. You should take that into account when writing code.


Examples?


To me, strdup is just another homework exercise out of K&R, like itoa.

Is POSIX strdup the same as K&R's?

--
pete
Nov 14 '05 #33

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

Similar topics

39
23573
by: Allan Bruce | last post by:
Hi there, I have a program written in c++ and I wish to use a similar function to strdup(). The reason I have problems is that the char array requires freeing to avoid a memory leak, but I get...
6
2932
by: Stefan Schwärzler | last post by:
Hi Ng, habe nicht besonders viel Erfahrung in C und C++, deshalb: möchte den befehl strdup in <string.h> verwenden. #include <string.h> attrib(char *name, char *val) : name(strdup(name)),...
37
4255
by: priya | last post by:
Hi all, I am using strdup() in my c program..But I am having some pr0blem while using the free() in my c code.here I am pasting the my code. #include <stdio.h>
53
651
by: klaushuotari | last post by:
Sorry to bother you, but I just have to. What about strdup()? It wasn't in standard C run-time library, yet many apps use it liberally as it was in there. I don't know if that particular...
20
6090
by: Michael Holm | last post by:
Ever so often when I try to compile some open source code, I get a error, pbrtparse.y(205) : error C3861: 'strdup': identifier not found In the example, I'm trying to compile pbrt...
5
3328
by: lovecreatesbea... | last post by:
I am trying the FREE net-snmp library things. Like the FREE libxml++ library, it lacks of a reasonable document on its API. Its very begining example code compiles and runs. It says "blah blah .."...
10
3901
by: thomas | last post by:
Hi, It's known that strdup() returns a char* type, but sometimes the following code generates warning messages. char *x = ... char *p = strdup(x); You must change it to
0
7193
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7067
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7264
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7316
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
7449
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5562
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
3148
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1495
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
728
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.