strtok and strtok_r

J

jacob navia

Richard said:
If you feel forced to resort to personal attacks, I can only assume you
have no logical arguments to put forward.

Personal attacks are allowed only for friends of Heathfield & Co.
 
R

Richard Heathfield

Charlie Gordon said:
If he would give a different answer on a different group, one of these
statements would be a lie or a joke.

....or a way of making a point, a la "Ich bin ein Berliner", with which
John F Kennedy bolstered the morale of West Berlin's citizens in June
1963. It was not "true" in the literal sense, but neither was it a lie
or a joke.

So he is a fundamentalist, ostracist, extremist...

If you feel forced to resort to personal attacks, I can only assume you
have no logical arguments to put forward.
 
C

Charlie Gordon

pete said:
Charlie said:
Sam Harris said:
On 15 Sep 2007 at 1:28, Charlie Gordon wrote:
You can easily write your own version
of strdup in a couple lines. I use
the following:

char *strdup(char *s)
{
char *r=0;
int i=0;
do {
r=(char *) realloc(r,++i * sizeof(char));
} while(r[i-1]=s[i-1]);
return r;
}

This proves my point.

Adding useful functions like strdup
would prevent newbies and jokers from
re-inventing them in the most cumbersome,
inefficient, ugly error prone ways.

Your function should take a const char *.
sizeof(char) is 1 by definition
Why do you cast the result of realloc ?
Your function invokes undefined behaviour
when running out of memory, it
should return NULL instead.

Intsead of using realloc in a loop,
I think most programmers would write strdup with
one function call to strlen and one to malloc and one to strcpy.

Or more efficiently calling memcpy instead of strcpy.

char *strdup(const char *str) {
size_t len;
char *dest = NULL;

if (str) {
len = strlen(str);
dest = malloc(len + 1);
if (dest) {
memcpy(dest, str, len);
dest[len] = '\0';
}
}
return dest;
}
 
F

Francine.Neary

"Sam Harris" <[email protected]> a écrit dans le message de (e-mail address removed)...


You can easily write your own version of strdup in a couple lines. I use
the following:
char *strdup(char *s)
{
char *r=0;
int i=0;
do {
r=(char *) realloc(r,++i * sizeof(char));
} while(r[i-1]=s[i-1]);
return r;
}

This proves my point.

Adding useful functions like strdup would prevent newbies and jokers from
re-inventing them in the most cumbersome, inefficient, ugly error prone
ways.

Your function should take a const char *.
sizeof(char) is 1 by definition
Why do you cast the result of realloc ?
Your function invokes undefined behaviour when running out of memory, it
should return NULL instead.

Even if it doesn't run out of memory, there's no reason to assume
realloc won't return a pointer to a different area of memory each
time: with the code above, this will lead to 1) memory leaks; 2) the
first part of the string is not copied properly.

The name strdup is also reserved for the implementation.

My suggestion would be:

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

char *my_strdup(const char *s)
{
size_t len;
char *t;
if(t=malloc(len=strlen(s)+1))
memcpy(t, s, len);
return t;
}
 
C

Charlie Gordon

Richard Heathfield said:
Charlie Gordon said:


...or a way of making a point, a la "Ich bin ein Berliner", with which
John F Kennedy bolstered the morale of West Berlin's citizens in June
1963. It was not "true" in the literal sense, but neither was it a lie
or a joke.

Except CBFalconer is no John F. Kennedy ;-)
His blunt rethoric does not bolster any one's morale, sarcasm does no good.
If you feel forced to resort to personal attacks, I can only assume you
have no logical arguments to put forward.

You are right, I should not have attributed to malice that which can be
adequately explained by plain ignorance. But I repeat: to not use strtok
anymore, check for availability of strtok_r or implement it locally from the
public domain source that has been posted above.
 
J

Joachim Schmitz

"Sam Harris" <[email protected]> a écrit dans le message de (e-mail address removed)...


You can easily write your own version of strdup in a couple lines. I use
the following:
char *strdup(char *s)
{
char *r=0;
int i=0;
do {
r=(char *) realloc(r,++i * sizeof(char));
} while(r[i-1]=s[i-1]);
return r;
}

This proves my point.

Adding useful functions like strdup would prevent newbies and jokers from
re-inventing them in the most cumbersome, inefficient, ugly error prone
ways.

Your function should take a const char *.
sizeof(char) is 1 by definition
Why do you cast the result of realloc ?
Your function invokes undefined behaviour when running out of memory, it
should return NULL instead.

Even if it doesn't run out of memory, there's no reason to assume
realloc won't return a pointer to a different area of memory each
time: with the code above, this will lead to 1) memory leaks; 2) the
first part of the string is not copied properly.

The name strdup is also reserved for the implementation.

My suggestion would be:

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

char *my_strdup(const char *s)
{
size_t len;
char *t;
if(t=malloc(len=strlen(s)+1))
memcpy(t, s, len);
return t;
}

It s is NULL, this version only returns NULL if the implemenation's
malloc(0) returns NULL too

Bye, Jojo
 
J

Joachim Schmitz

Joachim Schmitz said:
"Sam Harris" <[email protected]> a écrit dans le message de (e-mail address removed)...


On 15 Sep 2007 at 1:28, Charlie Gordon wrote:
Why did C99 get published without including the reentrant alternatives
to
strtok and similar functions is a mystery. I guess the national
bodies
were
too busy arguing about iso646.h. Other Posix utility functions are
missing
for no reason: strdup for instance. Did the Posix guys patent those or
is
WG14 allergic to unix ?
You can easily write your own version of strdup in a couple lines. I
use
the following:
char *strdup(char *s)
{
char *r=0;
int i=0;
do {
r=(char *) realloc(r,++i * sizeof(char));
} while(r[i-1]=s[i-1]);
return r;
}

This proves my point.

Adding useful functions like strdup would prevent newbies and jokers from
re-inventing them in the most cumbersome, inefficient, ugly error prone
ways.

Your function should take a const char *.
sizeof(char) is 1 by definition
Why do you cast the result of realloc ?
Your function invokes undefined behaviour when running out of memory, it
should return NULL instead.

Even if it doesn't run out of memory, there's no reason to assume
realloc won't return a pointer to a different area of memory each
time: with the code above, this will lead to 1) memory leaks; 2) the
first part of the string is not copied properly.

The name strdup is also reserved for the implementation.

My suggestion would be:

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

char *my_strdup(const char *s)
{
size_t len;
char *t;
if(t=malloc(len=strlen(s)+1))
memcpy(t, s, len);
return t;
}

It s is NULL, this version only returns NULL if the implementation's
malloc(0) returns NULL too
oops, sorry somehow my quoting was wrong.

Only the last sentence was mine...
 
C

Charlie Gordon

On 15 Sep 2007 at 1:28, Charlie Gordon wrote:
Why did C99 get published without including the reentrant alternatives
to
strtok and similar functions is a mystery. I guess the national bodies
were
too busy arguing about iso646.h. Other Posix utility functions are
missing
for no reason: strdup for instance. Did the Posix guys patent those or
is
WG14 allergic to unix ?
You can easily write your own version of strdup in a couple lines. I use
the following:
char *strdup(char *s)
{
char *r=0;
int i=0;
do {
r=(char *) realloc(r,++i * sizeof(char));
} while(r[i-1]=s[i-1]);
return r;
}

This proves my point.

Adding useful functions like strdup would prevent newbies and jokers from
re-inventing them in the most cumbersome, inefficient, ugly error prone
ways.

Your function should take a const char *.
sizeof(char) is 1 by definition
Why do you cast the result of realloc ?
Your function invokes undefined behaviour when running out of memory, it
should return NULL instead.

Even if it doesn't run out of memory, there's no reason to assume
realloc won't return a pointer to a different area of memory each
time: with the code above, this will lead to 1) memory leaks; 2) the
first part of the string is not copied properly.

No assumption is made about the return value of realloc pointing to
the same area. The above code will indeed cause memory leak when
running out of memory, but undefined behaviour will have been invoked
already since NULL is dereferenced then. Apart from that, the string
is copied correctly because realloc does preserve the contents of the
block it reallocates upto the smaller of old and new sizes.
The name strdup is also reserved for the implementation.

That's one more reason it should have been standardized in C99.
My suggestion would be:

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

char *my_strdup(const char *s)
{
size_t len;
char *t;
if(t=malloc(len=strlen(s)+1))
memcpy(t, s, len);
return t;
}

You code performs the task, but I find it misleading to call len a var
iable that is not the length of the string. I prefer to use size for
this purpose.

Furthermore, this code would not pass my default warning settings.
Assignment as an test expression is considered sloppy and error prone.
 
F

Francine.Neary

It s is NULL, this version only returns NULL if the implemenation's
malloc(0) returns NULL too

Entirely consistent with the standard library string functions - if
you pass them a char * that doesn't point to a string, the behavior is
undefined.

<OT>
And this is one case where "the thing you hope will happen" probably
doesn't - e.g. trying to compute strlen(NULL) on a GNU system produces
a seg fault).
 
C

Charlie Gordon

Joachim Schmitz said:
oops, sorry somehow my quoting was wrong.

Only the last sentence was mine...

And it does not make much sense ;-)
If s in NULL, strlen(s) invokes undefined behaviour.
otherwise, len is always> 0, and the code does not depend on the behaviour
of malloc(0)
 
F

Francine.Neary

<[email protected]> a écrit dans le message de (e-mail address removed)...


"Sam Harris" <[email protected]> a écrit dans le message de (e-mail address removed)...
On 15 Sep 2007 at 1:28, Charlie Gordon wrote:
Why did C99 get published without including the reentrant alternatives
to
strtok and similar functions is a mystery. I guess the national bodies
were
too busy arguing about iso646.h. Other Posix utility functions are
missing
for no reason: strdup for instance. Did the Posix guys patent those or
is
WG14 allergic to unix ?
You can easily write your own version of strdup in a couple lines. I use
the following:
char *strdup(char *s)
{
char *r=0;
int i=0;
do {
r=(char *) realloc(r,++i * sizeof(char));
} while(r[i-1]=s[i-1]);
return r;
}
This proves my point.
Adding useful functions like strdup would prevent newbies and jokers from
re-inventing them in the most cumbersome, inefficient, ugly error prone
ways.
Your function should take a const char *.
sizeof(char) is 1 by definition
Why do you cast the result of realloc ?
Your function invokes undefined behaviour when running out of memory, it
should return NULL instead.
Even if it doesn't run out of memory, there's no reason to assume
realloc won't return a pointer to a different area of memory each
time: with the code above, this will lead to 1) memory leaks; 2) the
first part of the string is not copied properly.

No assumption is made about the return value of realloc pointing to
the same area. The above code will indeed cause memory leak when
running out of memory, but undefined behaviour will have been invoked
already since NULL is dereferenced then. Apart from that, the string
is copied correctly because realloc does preserve the contents of the
block it reallocates upto the smaller of old and new sizes.
The name strdup is also reserved for the implementation.

That's one more reason it should have been standardized in C99.
My suggestion would be:
#include <stdlib.h>
#include <string.h>
char *my_strdup(const char *s)
{
size_t len;
char *t;
if(t=malloc(len=strlen(s)+1))
memcpy(t, s, len);
return t;
}

You code performs the task, but I find it misleading to call len a var
iable that is not the length of the string. I prefer to use size for
this purpose.

Furthermore, this code would not pass my default warning settings.
Assignment as an test expression is considered sloppy and error prone.

Tell that to Kernighan and Ritchie. :)

Is there a reason for the typo in your signature?
 
J

Joachim Schmitz

Charlie Gordon said:
And it does not make much sense ;-)
If s in NULL, strlen(s) invokes undefined behaviour.
otherwise, len is always> 0, and the code does not depend on the behaviour
of malloc(0)
Well, in one implementation that I have at hand strlen is documneted
return -1 on error (and sets errno), which led me to believe that
strlen(NULL) would do that too. Apparently not, just tested: it segfaults.

Oh well...

Bye, Jojo
 
J

Joachim Schmitz

Entirely consistent with the standard library string functions - if
you pass them a char * that doesn't point to a string, the behavior is
undefined.
Fair enough, but I'd prefer my own functions to do better than that, so I
like Charlie Gordon's implementation better.
<OT>
And this is one case where "the thing you hope will happen" probably
doesn't - e.g. trying to compute strlen(NULL) on a GNU system produces
a seg fault).
</OT>
Damn, here too...
anwyway: see above

Bye, Jojo
 
C

Charlie Gordon

Tell that to Kernighan and Ritchie. :)

They might read this thread, I am sure they would care to comment.

Coding conventions is a very effective tool to catch bugs at an early
stage in development. Using all the help the compiler and other
automated tools can give at tracking potential errors disguised as
suspicious use of certain operators enhances productivity.

There is no gain at writing

size_t len;
char *t;
if(t=malloc(len=strlen(s)+1)) ...

instead of

size_t size = strlen(s) + 1;
char *t = malloc(size);
if (t) ...

The latter is much more readable and less error prone.

Your version did improve on mine by using memcpy to copy the '\0'
instead of writing separate code for that.

--
Chqrlie.
Is there a reason for the typo in your signature?
chqrlie is my handle, is there a reason you don't sign your messages ?
 
J

Joachim Schmitz

Charlie Gordon said:
They might read this thread, I am sure they would care to comment.

Coding conventions is a very effective tool to catch bugs at an early
stage in development. Using all the help the compiler and other
automated tools can give at tracking potential errors disguised as
suspicious use of certain operators enhances productivity.

There is no gain at writing

size_t len;
char *t;
if(t=malloc(len=strlen(s)+1)) ...

instead of

size_t size = strlen(s) + 1;
char *t = malloc(size);
if (t) ...

The latter is much more readable and less error prone.

Your version did improve on mine by using memcpy to copy the '\0'
instead of writing separate code for that.

True but quite easy to fix:
char *my_strdup(const char *str) {
char *dest = NULL;

if (str) {
size_t size = strlen(str) + 1;
dest = malloc(size);
if (dest)
memcpy(dest, str, size);
}
return dest;
}
 
C

CBFalconer

Charlie said:
"pete" <[email protected]> a écrit:
.... snip ...
Intsead of using realloc in a loop, I think most programmers
would write strdup with one function call to strlen and one to
malloc and one to strcpy.

Or more efficiently calling memcpy instead of strcpy.

char *strdup(const char *str) {
size_t len;
char *dest = NULL;

if (str) {
len = strlen(str);
dest = malloc(len + 1);
if (dest) {
memcpy(dest, str, len);
dest[len] = '\0';
}
}
return dest;
}

I challenge the 'more efficient'. It will be highly dependent on
the compiler, but at the simplest you would be trading the effort
of an extra procedure call against the possible efficiency
improvement. Since most strings are short (in my case, probably
under 10 or 20 chars) this 'improvement' is a chimera. Also
bearing in mind that strdup is a system reserved name, my version
(with a #include <stdlib.h>) is:

char *dupstr(const char *str) {
char *dest, *temp;

if (dest = malloc(1 + strlen(str))) {
temp = dest;
while (*temp++ = *str++) continue;
}
return dest;
}

and I am willing to let it go boom when str is NULL, for early
warning etc. of problems.
 
C

CBFalconer

.... snip ...
<
Well, in one implementation that I have at hand strlen is
documneted return -1 on error (and sets errno), which led me to
believe that strlen(NULL) would do that too. Apparently not,
just tested: it segfaults.

That is not a C system. strlen returns a size_t, which is
unsigned, and thus can never return -1.
 
C

CBFalconer

Charlie said:
"CBFalconer" <[email protected]> a écrit:
.... snip about tknsplit and strtok ...
You must be joking Mr Falconer. You probably never heard of
Unix, or even Linux... Or do you live on this remote planet
Microsoft has not settled yet ? If you have no idea what
strtok_r is, learn something new today:
http://linux.die.net/man/3/strtok_r
or if you like Microsoft's version better (part of the secure
string proposal)
http://msdn2.microsoft.com/en-us/library/ftsafwz3(VS.80).aspx

This newsgroup is comp.lang.c. C is defined by the various C
standards, present or past, and includes K&R for times previous to
1989. None of these define, or even mention, strtok_r. Thus,
without standard C code, published in the same message, discussion
of it is off-topic here. The name is still reserved for the
implementor. As I said, it doesn't exist. Unix, Linux, Microsoft
have no influence whatsoever.
 
J

Joachim Schmitz

CBFalconer said:
... snip ...
<

That is not a C system. strlen returns a size_t, which is
unsigned, and thus can never return -1.
It claimed to be POSIX compliant. Prototype is indeed
size_t strlen(const char*s);
It's man-paged says it to return (size_t)-1 and set errno in case of an
error.
Apparently strlen(NULL) isn't regarded an error, as it segfaults then...

Bye, Jojo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top