2009-06-04 14 views
6

la pista está en el título, pero básicamente he heredado un código que tiene más de 800 instancias de strcpy. Quiero escribir una nueva función y luego reemplazar strcpy con strcpy_mine.strcpy ... quiero reemplazar con strcpy_mine que terminará strncpy y null

Así que estoy tratando de determinar qué lista de parámetros tendrá strcpy_mine.

me trataron:

void strcpy_mine(char* pTarget, const char* const pCopyMe) 
{ 
    const unsigned int lenAlwaysFour = sizeof(pCopyMe); //:(
    strncpy(pTarget, pCopyMe, lenAlwaysFour); 

    //add extra terminator in case of overrun 
    pTarget[lenAlwaysFour] = 0; 
} 

pero el sizeof es siempre 4 pCopyMe es un puntero

lo que no quiero hacer es sustituir

strcpy (buf, pCopyMe); 

con

strncpy (buf, pCopyMe, sizeof(pCopyMe)); buf[sizeof(pCopyMe)] = 0; 

alguna idea? (Strcpy_l no está disponible)

aplausos

Respuesta

4

Dependiendo de cómo las llamadas sitios parecen, a menudo la mayoría de los casos puede ser manejado por una simple plantilla:

#include <string.h> 

template <int bufferSize> 
void strcpy_mine(char (&pTarget)[bufferSize], const char* const pCopyMe) 
{ 
    strncpy(pTarget, pCopyMe, bufferSize-1); 

    //add extra terminator in case of overrun 
    pTarget[bufferSize-1] = 0; 
} 

int main() 
{ 
    char buf[128]; 
    strcpy_mine(buf,"Testing"); 
    return 0; 
} 

Si está utilizando Microsoft Visual Studio 2005 o más reciente, véase Secure Template Overloads para una implementación de Microsoft .

+0

¡salud!esto es casi lo que estoy buscando, pero aún me obliga a poner el tamaño del buffer en chevrones, aunque char buf [200]; strcpy_mine <200> (buf, pString); – timB33

+0

strCpyMine (buf, pString); – timB33

+0

Entonces estás haciendo algo diferente. ¿Compilador obsoleto? – MSalters

11

sizeof() devuelve el tamaño del tipo - en este caso const char* const que serán 4 en máquinas de 32 bits.

Creo que cree que quiere strlen(). Pero esa no es la forma correcta de usar las funciones de strncpy. Necesita el tamaño del salida buffer para strncpy.

Para solucionar esto, debe examinar el código en cada sitio de llamadas, calcular el tamaño del búfer de salida y pasarlo como un argumento al strcpy_mine. Si el sitio de llamada para strcpy (o strcpy_mine) no conoce el tamaño del búfer de salida, debe buscar hacia atrás en el código de la ubicación que asigna el búfer, y pasar el tamaño hasta el sitio strcpy .

Básicamente no puede escribir un reemplazo en reemplazo de strcpy que toma los mismos argumentos y espera evitar los problemas que produjeron strncpy en primer lugar (y mejores reemplazos más allá de eso). Puede crear una función que tome los mismos argumentos que strncpy, pero asegura que el resultado sea nulo; termine la implementación de la función OpenBSD's strlcpy(). Pero el primer paso debe ser cambiar los sitios de llamadas para transmitir el conocimiento del tamaño del búfer de salida.

+0

+1 para strlcpy. Al escribir mi propia función similar a esta, también paso una enumeración {AllOrNothing, TruncateOkay} a la función para que maneje los casos de desbordamiento. – Dolphin

1

Puede usar la misma lista de parámetros que strncpy para strcpy_mine, pero escríbala para que siempre sea nula y finalice el resultado. No debería ser muy difícil de hacer.

Un desafío, sin embargo, es que algunos de los códigos existentes que llaman a strcpy() pueden no conocer el tamaño del búfer.

+0

Lo segundo. Tendrá que agregar otro parámetro para el tamaño del búfer de salida. El método strcpy es una fuente clásica de errores de desbordamiento de búfer. Microsoft incluso ha desaprobado esta función a favor de algo así como strncpy. – Mark

0

También puede usar macros para evitar ediciones múltiples. O automatice la edición mediante algún script.

+0

En caso de que te importe, macro es singular, macros es plural. Macroses no es una palabra. Supongo que el inglés no es tu lengua materna. Solo estoy tratando de ayudarte. – jmucchiello

0

Definitivamente debe pasar el tamaño del búfer de destino como parámetro, como han dicho otras personas anteriormente.

Esto es un poco fuera de tema, pero sólo quiero señalar que, después de utilizar strncpy(), es necesario configurar para anular el último carácter de la memoria intermedia, que tiene el índice 1 menos que la longitud (no la longitud del buffer):

strncpy (buf, pCopyMe, buflen); buf[buflen - 1] = '\0'; 

O, alternativamente, puede utilizar strncat() en una cadena vacía, pasándole una longitud que es 1 menos, y que garantizará a nulo finalizar su cadena:

buf[0] = '\0'; strncat (buf, pCopyMe, buflen - 1); 
+0

si está de acuerdo con eso, ¿por qué no?: Strncpy (buf, pCopyMe, buflen) [buflen-1] = '\ 0'; :-) –

+0

@Anders: ¡¡¡Genial !!! – jmucchiello

0

Douglas Leeder tiene razón. Hay un límite en la utilidad de reemplazar strcpy a menos que esté dispuesto a hacer el arduo trabajo de pasar una buena y sana longitud de búfer en cada instancia. ¡Eso es mucho trabajo!

¡La buena noticia es que vale la pena! Hace algunos años, participé en varios proyectos de C++ que eran tardíos, con errores y poco confiables. Al declarar prohibido strcpy y strlen, y tomar 2-3 días del proyecto para reemplazarlos por strnclen/strnlen personalizados, en todos estos proyectos, de repente, podríamos funcionar durante días en lugar de horas. También vimos una gran cantidad de cadenas truncadas aparecer en pantallas y archivos de registro. Eso nos dio las pistas necesarias para rastrear los problemas de truncamiento, problemas que antes se bloqueaban.

Si no desea hacer esto, puede obtener un beneficio mucho más pequeño simplemente marcando ambos parámetros de puntero para NULL, y limitando el tamaño máximo de una copia de cadena y registrando todas las veces que se alcanza el límite. No hagas un strlen de ninguno de los parámetros, ya que Strlen felizmente se colgará de ti si la cadena no termina correctamente.

Hoy en día, los proyectos nuevos usan buenos objetos de cadena, pero hay un montón de código heredado que no lo hace.

2

Un poco periférico, tal vez, pero como nadie lo mencionó y aparece en el título: no se puede (legalmente) escribir una función global llamada strcpy_mine().

El "espacio de nombre" de las funciones cuyos nombres comienzan con str está reservado para la biblioteca estándar. Ver, por ejemplo, the accepted answer to this question.

+0

interesante, aplausos :) – timB33

Cuestiones relacionadas