strdup() – ¿Qué hace en C?

8 minutos de lectura

avatar de usuario
Manoj Dudas

¿Cuál es el propósito de la strdup() función en C?

  • también está strdupa() (en la biblioteca GNU C), una buena función que es similar a strdup(), pero asigna memoria en la pila. Su programa no necesita liberar la memoria explícitamente como en el caso de strdup(), se liberará automáticamente cuando salga de la función donde se llamó a strdupa()

    – dmityugov

    31 de octubre de 2008 a las 13:05

  • strdupa es peligroso y no debe usarse a menos que ya haya determinado que strlen es muy pequeño. Pero entonces podría usar una matriz de tamaño fijo en la pila.

    – R.. GitHub DEJA DE AYUDAR A ICE

    29 de diciembre de 2010 a las 16:34

  • @slacker google translate no está siendo útil… ¿Qué significa strdup/strdupa significa en polaco?

    – haneefmubarak

    7 de marzo de 2015 a las 16:47

  • @haneefmubarak aquí

    – anatolyg

    30/09/2015 a las 17:02

  • Aquí está la diferencia entre strdup y strcpy stackoverflow.com/questions/14020380/strcpy-vs-strdup

    – Shiva Prakash

    21 de agosto de 2018 a las 8:31

Exactamente como suena, suponiendo que esté acostumbrado a la forma abreviada en que C y UNIX asignan palabras, cadenas duplicadas 🙂

Teniendo en cuenta que en realidad no es parte del estándar ISO C en sí mismo(un) (es una cosa POSIX), efectivamente está haciendo lo mismo que el siguiente código:

char *strdup(const char *src) {
    char *dst = malloc(strlen (src) + 1);  // Space for length plus nul
    if (dst == NULL) return NULL;          // No memory
    strcpy(dst, src);                      // Copy the characters
    return dst;                            // Return the new string
}

En otras palabras:

  1. Intenta asignar suficiente memoria para contener la cadena anterior (más un carácter ‘\0’ para marcar el final de la cadena).

  2. Si la asignación falla, establece errno para ENOMEM y regresa NULL inmediatamente. Ajuste de errno para ENOMEM es algo malloc hace en POSIX por lo que no necesitamos hacerlo explícitamente en nuestro strdup. Si tu eres no Cumple con POSIX, ISO C en realidad no exige la existencia de ENOMEM así que no he incluido eso aquí(b).

  3. De lo contrario, la asignación funcionó, así que copiamos la cadena anterior a la nueva cadena(C) y devolver la nueva dirección (que la persona que llama es responsable de liberar en algún momento).

Tenga en cuenta que esa es la definición conceptual. Cualquier escritor de bibliotecas que valga su salario puede haber proporcionado un código altamente optimizado dirigido al procesador en particular que se está utilizando.


(un) Sin embargo, las funciones que comienzan con str y una letra minúscula están reservados por el estándar para direcciones futuras. Desde C11 7.1.3 Reserved identifiers:

Cada encabezado declara o define todos los identificadores enumerados en su subcláusula asociada, y * opcionalmente declara o define los identificadores enumerados en su subcláusula de instrucciones de biblioteca futura asociada. **

Las direcciones futuras para string.h puede encontrarse en C11 7.31.13 String handling <string.h>:

Nombres de funciones que comienzan con str, memo wcs y se puede agregar una letra minúscula a las declaraciones en el <string.h> encabezamiento.

Así que probablemente deberías llamarlo de otra manera si quieres estar seguro.


(b) El cambio sería básicamente reemplazar if (d == NULL) return NULL; con:

if (d == NULL) {
    errno = ENOMEM;
    return NULL;
}

(C) Tenga en cuenta que uso strcpy por eso ya que eso muestra claramente la intención. En algunas implementaciones, puede ser más rápido (dado que ya conoce la longitud) de usar memcpy, ya que pueden permitir la transferencia de datos en fragmentos más grandes o en paralelo. O puede que no 🙂 Mantra de optimización #1: “medir, no adivinar”.

En cualquier caso, si decides ir por ese camino, harías algo como:

char *strdup(const char *src) {
    size_t len = strlen(src) + 1;       // String plus '\0'
    char *dst = malloc(len);            // Allocate space
    if (dst == NULL) return NULL;       // No memory
    memcpy (dst, src, len);             // Copy the block
    return dst;                         // Return the new string
}

  • Vale la pena señalar que, como implica la implementación de muestra de Pax, strdup (NULL) no está definido y no es algo que pueda esperar que se comporte de ninguna manera predecible.

    – relajarse

    22 de mayo de 2009 a las 10:14

  • Además, creo que malloc() configuraría errno, por lo que no debería tener que configurarlo usted mismo. Pienso.

    – Chris Lutz

    8 de junio de 2009 a las 3:58

  • @Alcot, strdup es para aquellas situaciones en las que desea que se asigne memoria en montón para la copia de cadena. De lo contrario, tienes que hacerlo tú mismo. si ya tener un búfer lo suficientemente grande (mallocado o no), sí, use strcpy.

    – pax diablo

    28 de febrero de 2012 a las 1:15

  • @acgtyrant: si, por estándar, se refiere al estándar ISO (el estándar C real), no, no es parte de él. Eso es parte del estándar POSIX. Sin embargo, hay un montón de C implementaciones que lo proporcionan, a pesar de no ser una parte oficial de ISO C. Sin embargo, incluso si no lo hicieran, las cinco líneas en esta respuesta deberían ser más que suficientes.

    – pax diablo

    16 de abril de 2014 a las 10:37

  • Buen punto, @chux, solo mandatos ISO { EDOM, EILSEQ, ERANGE } como códigos de error requeridos. He actualizado la respuesta para dar cuenta de esto.

    – pax diablo

    30 de enero de 2018 a las 6:13

avatar de usuario
Chris joven

No tiene sentido repetir las otras respuestas, pero tenga en cuenta que strdup() puede hacer lo que quiera desde una perspectiva de C, ya que no es parte de ningún estándar de C. Sin embargo, está definido por POSIX.1-2001.

  • Es strdup() ¿portátil? No, no está disponible en un entorno que no sea POSIX (de todos modos, se puede implementar trivialmente). Pero decir que una función POSIX puede hacer cualquier cosa es bastante pedante. POSIX es otro estándar eso es tan bueno como el de C e incluso más popular.

    – PP

    9 de mayo de 2014 a las 8:58

  • @BlueMoon Creo que el punto es que una implementación de C que afirma no cumplir con POSIX aún puede proporcionar un strdup funcionar como una extensión. En tal implementación, no hay garantía de que eso strdup se comporta de la misma manera que la función POSIX. No conozco ninguna implementación de este tipo, pero una implementación legítima no maliciosa podría proporcionar char *strdup(char *) por razones históricas, y rechazar los intentos de pasar por una const char *.

    usuario743382

    6 de marzo de 2015 a las 22:19

  • ¿Cuál es la diferencia entre el estándar C y POSIX? ¿Por estándar C quiere decir que no existe en las bibliotecas estándar de C?

    – Koray Tugay

    22 de marzo de 2015 a las 11:35

  • @KorayTugay Son estándares diferentes. Es mejor tratarlos como si no estuvieran relacionados, a menos que sepa que el estándar para una función C en particular se ajusta al estándar POSIX y que su compilador/biblioteca se ajusta al estándar para esa función.

    – Mateo Lee

    23/03/2015 a las 19:40


avatar de usuario
patricio schlüter

char * strdup(const char * s)
{
  size_t len = 1+strlen(s);
  char *p = malloc(len);

  return p ? memcpy(p, s, len) : NULL;
}

Tal vez el código es un poco más rápido que con strcpy() como el \0 char no necesita ser buscado nuevamente (Ya estaba con strlen()).

  • Gracias. En mi implementación personal lo hago aún “peor”. return memcpy(malloc(len), s, len); ya que prefiero el colapso de la asignación en lugar de la NULL en la falla de asignación.

    – Patrick Schlüter

    30 de diciembre de 2010 a las 21:00

  • @tristopia desreferenciando NULL no tiene que chocar; es indefinido. Si quiere estar seguro de que falla, escriba un emalloc que llama abort al fallar.

    – Dave

    30 de diciembre de 2011 a las 3:28

  • Lo sé, pero se garantiza que mi implementación solo se ejecutará en Solaris o Linux (por la naturaleza misma de la aplicación).

    – Patrick Schlüter

    30 de diciembre de 2011 a las 13:01

  • @tristopia: Es bueno tener la costumbre de hacer las cosas de la mejor manera. Adquiera el hábito de usar emalloc incluso si no es necesario en Solaris o Linux para que lo use en el futuro cuando escriba código en otras plataformas.

    – El arte de la guerra

    28/02/2015 a las 20:20

avatar de usuario
VonC

Desde hombre tirado:

Él strdup() La función devolverá un puntero a una nueva cadena, que es un duplicado de la cadena a la que apunta s1. El puntero devuelto se puede pasar a free(). Se devuelve un puntero nulo si no se puede crear la nueva cadena.

avatar de usuario
sujay kumar

strdup y strndup se definen en los sistemas compatibles con POSIX como:

char *strdup(const char *str);
char *strndup(const char *str, size_t len);

Él strdup() función asigna suficiente memoria para una copia de la cadena strhace la copia y le devuelve un puntero.

El puntero se puede utilizar posteriormente como argumento de la función. free.

Si no hay suficiente memoria disponible, NULL se devuelve y errno se establece en
ENOMEM.

Él strndup() copias de funciones como máximo len caracteres de la cadena str siempre nulo terminando la cadena copiada.

avatar de usuario
paxdiablo

La declaración:

strcpy(ptr2, ptr1);

es equivalente a (aparte del hecho de que esto cambia los punteros):

while(*ptr2++ = *ptr1++);

Mientras:

ptr2 = strdup(ptr1);

es equivalente a:

ptr2 = malloc(strlen(ptr1) + 1);
if (ptr2 != NULL) strcpy(ptr2, ptr1);

Entonces, si desea que la cadena que ha copiado se use en otra función (como se crea en la sección del montón), puede usar strdupdemás strcpy es suficiente,

avatar de usuario
Zaffy

strdup() realiza una asignación de memoria dinámica para la matriz de caracteres, incluido el carácter final ‘\0’, y devuelve la dirección de la memoria del montón:

char *strdup (const char *s)
{
    char *p = malloc (strlen (s) + 1);   // allocate memory
    if (p != NULL)
        strcpy (p,s);                    // copy string
    return p;                            // return the memory
}

Entonces, lo que hace es darnos otra cadena idéntica a la cadena dada por su argumento, sin requerir que asignemos memoria. Pero todavía tenemos que liberarlo, más tarde.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad