cc-stringsstrdup

Is this a legal C strdup function?


I tried to make my own strdup function to practice my C skills, but I'm not sure if it's legal or not.

the function is down below:

char*
strdup(char* str) {
    char* dup_str;
    int len;
    for (len = 0; *str != '\0'; ++len) {
        dup_str = str;
        dup_str++;
        str++;
    }
    
    dup_str -= len;
    return dup_str;
}

I have tested it a bit, but I'm still not sure if it is legal. It may be completely incorrect, so I'm surprised that it works the way it does at the moment.


Solution

  • Ignoring the undefined behaviour that occurs for strings larger than INT_MAX chars long, your code is equivalent to the following:

    char *my_strdup( char *old ) {  // XXX Shouldn't require a modifiable string.
       if ( *old ) {
          return old;               // XXX Not a pointer to a new string.
       } else {
          char* indeterminate;
          return indeterminate;     // XXX Indeterminate value.
       }
    }
    

    This is completely wrong. For starters, strdup's main purpose is to allocate a new string, yet your function allocates no memory.

    strdup can be summarized into four steps:

    1. Determine the amount of memory to allocate.
    2. Allocate memory for the new string.
    3. Copy the old string into the newly-allocated buffer.
    4. Return the pointer to the newly-allocated buffer.

    Fixed: (Added after OP made attempt to fix in the comments.)

    char *my_strdup( const char* old ) {
       size_t n = strlen( old ) + 1;
       char *new = malloc( n );
       if ( !new ) {
          errno = ENOMEM;
          return NULL;
       }
    
       return memcpy( new, old, n );
    }
    

    We can also replace the other string functions.

    size_t my_strlen( const char *str ) {
       size_t len = 0;
       while ( *( str++ ) )
          ++len;
    
       return len;
    }
    
    void *my_memcpy( void *restrict dst, const void *restrict src, size_t count ) {
       void *rv = dst;
    
       while ( count-- )
          *( dst++ ) = *( src++ );
    
       return rv;
    }