[prog] [C] strings bug

Laurel Fan laurel at sdf.lonestar.org
Wed Apr 9 17:22:14 EST 2003


See explanation inline with the quoted code:

On Wed, Apr 09, 2003 at 10:55:02PM +0100, Conor Daly wrote:
> char *strset(char *dest, const char *src) {
> 	/* This is just a wrapper for strdup() which handles
> 	 * all the necessary stuff
> 	 * Since strdup() allocates a new string, we need to
> 	 * set the target to become the returned pointer
> 	 *
> 	 * Useage: dest = strset(dest, src);
> 	 *
> 	 * Unfortunately, we need the address of the old string so we 
> 	 * can free that, otherwise we get a memory leak.
> 	 *
> 	 */
> 
> 
> 	/* create a tmp string to hold 'dest' while we free that */
> 	char *tmp;

The problem is with the inital value of tmp.  When you declare a local
variable, its initial value is undefined.  See below...

> 	return(strdup(src));/* This is a memory leak */
> 	/* comment out the line above to see the bug in action */
> 
> 	printf("in function strset()\n");
> 	if(dest)
> 	{
> 
> 	/* take a copy of dest */
> 	if( (tmp = strdup(dest)) == NULL)

tmp might be set here, but only if dest was not NULL.

> 		{
> 			return(dest); /* we failed to make a copy so bail
> 					out */
> 		}
> 	/* then free it */
> 	free(dest);
> 	}
> 	/* now use strdup() to replace the old string with the new */
> 	if( (dest = strdup(src)) == NULL) {
> 		  printf("Failed to set dest\n");
> 	/* the copy failed so we want to return the original string
> 	unchanged.
> 	 */
> 		return(tmp);
> 	} else {
> 		/* free the tmp string */
> 		free(tmp);

Here, it is possible that the value of tmp is not defined (which means
it could be anything), so freeing this value can have unpredictable
results.

> 		/* and return the new pointer to dest */
> 		return(dest);
> 	}
> }
> /* *************end strset()**************************/

That said, the way I would do it avoids copying dest altogether:

char *strset(char *string_to_replace, onst char *src) {
    /*
        Return a newly allocated copy of src.
        If successful, string_to_replace will be freed.
        If unsuccessful, no new memory will be allocated, and
	string_to_replace will be returned unchanged.
    */

    char *new_copy_of_src = strdup(src);

    if (new_copy_of_src == NULL) {
        /* printf("Copying src string failed\n"); */
        return(string_to_replace);
    } else {
	/* printf("Copying src string succeeded\n") */
        free(string_to_replace);
        return(new_copy_of_src);
    }
}


-- 
laurel at sdf.lonestar.org
http://dreadnought.gorgorg.org


More information about the Programming mailing list