Why do you not have to free when using strrchr?

A

Angus

Hello

result is a pointer so why is there no need to free allocated memory after
using strrchr?

Eg

#include <string.h>
#include <stdio.h>

char string[100] = "Find the last 'a' in this string", *result;

main()
{
/* Return a pointer to the last: 'a' */
result = strrchr(string, 'a');
printf("The remainder of the string starting at the first\n");
printf("'a' is: %s", result);
}
 
C

Clever Monkey

Angus said:
result is a pointer so why is there no need to free allocated memory after
using strrchr?

Eg

#include <string.h>
#include <stdio.h>

char string[100] = "Find the last 'a' in this string", *result;

main()
{
/* Return a pointer to the last: 'a' */
result = strrchr(string, 'a');
printf("The remainder of the string starting at the first\n");
printf("'a' is: %s", result);
}
I'm sure the gurus here can cite chapter-and-verse, but in your example
I see no allocated memory. In this code you have a static char array,
and strrchr() is simply returning an offset into that. It is not
returning newly allocated memory, but an offset into an already
allocated chunk of string.
 
R

Richard Heathfield

Angus said:
Hello

result is a pointer so why is there no need to free allocated memory after
using strrchr?

Because you didn't allocate it, using malloc/calloc/realloc. It returns a
pointer into an area you're managing in some other way. In your (snipped)
example, the memory for the array has file scope and static storage
duration, so it'll hang around for the lifetime of the program. This is
true whether or not you call strrchr on it.

In fact, the only time where you might conceivably pass the result of
strrchr() to free() would be in the case where you /did/ allocate the
memory via malloc/calloc/realloc *and* strrchr happens to return a pointer
to the first character in the string stored in that memory:

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

int main(void)
{
char *needle = NULL;
char *haystack = malloc(1024 * sizeof *haystack);
if(haystack != NULL)
{
strcpy(haystack, "Now is the time to party.");
needle = strrchr(haystack, 'N');
free(needle); /* legal in the same way that wearing your socks
inside-out is legal - WHY would you choose
to do that? */

/* haystack is now indeterminate */
}
return 0;
}
 
C

CBFalconer

Richard said:
Angus said:


Because you didn't allocate it, using malloc/calloc/realloc. It
returns a pointer into an area you're managing in some other way.
In your (snipped) example, the memory for the array has file scope
and static storage duration, so it'll hang around for the lifetime
of the program. This is true whether or not you call strrchr on it.

In fact, the only time where you might conceivably pass the result
of strrchr() to free() would be in the case where you /did/
allocate the memory via malloc/calloc/realloc *and* strrchr
happens to return a pointer to the first character in the string
stored in that memory:

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

int main(void)
{
char *needle = NULL;
char *haystack = malloc(1024 * sizeof *haystack);
if(haystack != NULL)
{
strcpy(haystack, "Now is the time to party.");
needle = strrchr(haystack, 'N');
free(needle); /* legal in the same way that wearing your socks
inside-out is legal - WHY would you choose
to do that? */

/* haystack is now indeterminate */
}
return 0;
}

That is a highly newbie confusing example. If the argument to
strchr is 'o' the free call will bomb. Yet it will run with an
argument 'z'. He probably won't have a clue why.
 
R

Richard Heathfield

CBFalconer said:

That is a highly newbie confusing example.

Yes, it was an intentional example of How Stupid Code Can Be Legal But Still
Stupid (tm). I couldn't think of a non-stupid example for passing the
result of strrchr() to free(). (Can you?)
 
R

Richard Tobin

Richard Heathfield said:
Yes, it was an intentional example of How Stupid Code Can Be Legal But Still
Stupid (tm). I couldn't think of a non-stupid example for passing the
result of strrchr() to free(). (Can you?)

So that I don't have to keep track of which strings are malloc()ed and
which aren't, I always malloc() an extra byte, put a Q at the
beginning, and then increment the pointer. For non-malloc()ed
strings, I put a nul at the beginning and increment. Thanks to my
personal theory of English spelling, I never need to use Qs otherwise.
That way I can use the string normally, and call

free(strrchr(s, 'Q'))

when I don't need it any more. This will free it if it was malloc()ed,
and do a harmless free(0) otherwise.

-- Richard
 
K

Keith Thompson

So that I don't have to keep track of which strings are malloc()ed and
which aren't, I always malloc() an extra byte, put a Q at the
beginning, and then increment the pointer. For non-malloc()ed
strings, I put a nul at the beginning and increment. Thanks to my
personal theory of English spelling, I never need to use Qs otherwise.
That way I can use the string normally, and call

free(strrchr(s, 'Q'))

when I don't need it any more. This will free it if it was malloc()ed,
and do a harmless free(0) otherwise.

A more realistic theory of English could use, say, '\xff' rather than 'Q'.
 
R

Richard Tobin

free(strrchr(s, 'Q'))
[/QUOTE]

[That should have been "strrchr(s-1, 'Q')]
A more realistic theory of English could use, say, '\xff' rather than 'Q'.

Kwite so, but if I was aiming for realism (or at least, slightly
closer to it), I would use strchr() instead of strrchr(), then it
wouldn't matter if I used the character in the string.

-- Richard
 
K

Kenneth Brody

CBFalconer said:
Richard said:
Angus said:
result is a pointer so why is there no need to free allocated
memory after using strrchr?
[...]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char *needle = NULL;
char *haystack = malloc(1024 * sizeof *haystack);
if(haystack != NULL)
{
strcpy(haystack, "Now is the time to party.");
needle = strrchr(haystack, 'N');
free(needle); /* legal in the same way that wearing your socks
inside-out is legal - WHY would you choose
to do that? */

/* haystack is now indeterminate */
}
return 0;
}

That is a highly newbie confusing example. If the argument to
strchr is 'o' the free call will bomb. Yet it will run with an
argument 'z'. He probably won't have a clue why.

For the benefit new any newbies lurking...

free'ing the return from strrchr(haystack,'o') will pass the address
of the 'o' in "to" within the malloc'ed buffer, which is illegal.
(You can only pass the actual malloc'ed buffer address.)

free'ing the return from strrchr(haystack,'z') will pass NULL to
free(), as there is no 'z' in the haystack, which is valid. (To
amend the prior parenthetical statement -- you can also pass NULL
to free, which is effectively a no-op.)

Note, too, that I have used pre-ANSI C compilers in which passing
NULL to free() was a guaranteed crash. However, this was many
years ago.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top