2011-03-17 12 views
5

Llamo algunas funciones C++ dentro de un manejador de señal y mi programa finaliza por falla de segmentación. Cuando consulto gdb, la función memcpy() es donde obtengo SIGSEGV. Me gustaría saber si memcpy() es una función de reentrada o no?¿Se reentrató la función memcpy()?

+0

Mire dónde el manejador de señales obtiene los valores del puntero y la longitud que utiliza. 'memcpy' es seguro, pero si haces algo como' free (somestruct-> data); somestruct-> data = 0; somestruct-> len = 0; 'entonces, por supuesto, la señal podría ocurrir en el medio de eso. –

Respuesta

1

No veo por qué no podría ser reentrante. No estoy seguro, pero creo que está basado en las bibliotecas que usa.

11

En todas las plataformas salvo en las más integradas, se volverá a ingresar. Mencionas SIGSEGV así que supongo que no es uno de esos. En este caso, lo más probable es que memcpy() no sea el culpable: es culpa del que llama. Si le pides a memcpy() que copie los punteros malos (o la longitud incorrecta), entonces será el que falle. Desde aquí se puede hacer esto:

memcpy(NULL, NULL, 123456789); 

que va a causar una violación de segmento y se te dirá memcpy() causado. Por supuesto, no es culpa de Memcpy, solo está haciendo lo que le dijiste. Su manejador de señal lo está llamando con algo extraño. Una traza inversa (en gdb o cualquier herramienta que tenga) en el sitio de la persona que llama debe mostrar con qué lo llamó. En su defecto, simplemente imprima los argumentos que está pasando a memcpy.

+2

Posix dice que no se puede llamar a memcpy desde un manejador de señal. En la práctica, puede funcionar. La mayoría de las veces, al menos. Pero no está garantizado en absoluto. –

+1

@James: la forma de comprobarlo, supongo, sería reemplazar la llamada a 'memcpy' con el bucle obvio y ver si aún se produce la segfault. Si se va, entonces 'memcpy' no era asincrónico-seguro para señales. Si no es así, entonces o bien el problema está en otra parte que la copia real, o bien es algo sutil que hacer con el acceso 'char' que no sea señal-atómico. –

+1

@James Eso es extremadamente sorprendente.No puedo encontrar una referencia a que memcpy() no sea seguro para señales (incluso desde opengroup). En algunas arquitecturas de microcontroladores/DSP, no es reentrante debido a que tiene ubicaciones estáticas para sus variables locales, pero no puedo imaginarme cómo lograría que no sea seguro para otras arquitecturas sin esforzarme mucho por hacerlo realidad. ¿Tienes un enlace? –

2

Parte de la información pertinente relativa a las funciones de reentrada (no) y manejadores de señales (en la medida pertinente a la biblioteca GNU C) se puede encontrar en http://www.gnu.org/s/libc/manual/html_node/Nonreentrancy.html#Nonreentrancy:

Esta parte parece especialmente relevante a su pregunta:

  • "La simple lectura de un objeto de memoria es segura siempre que pueda tratar con cualquiera de los valores que puedan aparecer en el objeto en el momento en que se puede entregar la señal. Tenga en cuenta que la asignación a algunos tipos de datos requiere más de una instrucción, lo que significa que el controlador podría ejecutar "en el medio de" un ssignment a la variable si su tipo no es atómico ".

  • "La mera escritura en un objeto de memoria es segura siempre que un cambio repentino en el valor, en cualquier momento cuando el manejador se ejecute, no perturbe nada".

0

A menos que memcpy se haya implementado MAL, es reentrante. Solo funcionará con lo que le dé: los punteros y el valor de la longitud. Todos los parámetros se pasan por valor, por lo que una vez que se ha activado la función, estos valores no cambiarán en su marco de pila, independientemente de las señales u otros hilos.

0

Creo que el problema es que está utilizando como parámetros para la función memcpy un puntero no válido (o eliminado), compruebe su código cuidadosamente.

Atentamente.