Pregunta

He estado tratando de rastrear un error de bloqueo intermitente en mi código (que usa setJMP), y lo reducí para: aparece al compilar con /o2, desaparece con /o2 /oy-, es decir, solo aparece con omitir puntero de marco.

http://msdn.microsoft.com/en-us/library/2kxx5t2c(v=vs.80).aspx Sugiere que SetJMP requiere un puntero de cuadro. De este modo:

  1. Parece que cuando un programa que usa SETJMP se compila con /O2, Visual C ++ genera silenciosamente un código que causa corrupción intermitente de la pila. ¿Es esto cierto, o me estoy perdiendo algo?

  2. Me parece que solo la función que invoca SETJMP debe ser compilada con el puntero de cuadro, el resto del programa, incluso las funciones que llaman LongJMP, deberían estar bien para omitir el puntero de marcos. ¿Es esto cierto?

Editar: Lo he reducido un poco más.

Habilitar el puntero de cuadro en la función que llamaba a SetJMP no hizo ninguna diferencia, pero eso se debe a que el compilador ya estaba haciendo eso, tal como debería, obviamente notando que debía hacerse y hacerlo automáticamente.

Lo que hizo la diferencia fue permitir el puntero de cuadro en Main. Eso no es tan extraño como parece, ya que el choque se manifestó a cambio de Main. Ahora que lo pienso, todos los ejemplos que puedo encontrar en una búsqueda rápida de Google del uso de SetJMP, hágalo en Main. Quizás sucedió que el equipo de Microsoft Compiler solo lo probó de esa manera.

Esa es la forma idiomática de usarlo, tal vez la mejor solución sería para mí simplemente en línea la función de uso de SetJMP en Main.

¿Fue útil?

Solución

De acuerdo, he publicado un informe de errores con un caso de prueba autónomo, así que espero que una solución esté en proceso: http://connect.microsoft.com/visualstudio/feedback/details/6666704/visual-c-generates-incorrect-code-with-omit-frame-pointer-and-setjmp

Mientras tanto, la solución es no usar el puntero de marco omitir, o poner el código que llama a SetJMP en Main, o poner la función que llama a LongJMP en el mismo archivo de origen que la llamada a SetJMP.

Otros consejos

¿Puede especificar más información sobre el bloqueo en sí? Quiero decir, qué código de compilador generado para el longjmp, ¿ocurre el accidente inmediatamente después del longjmp, o cuando intenta acceder a variables automáticas, o cuando intenta salir de la función?

Supongo que el objetivo La función debe compilarse con el marco de pila estándar, parece que no hay una limitación razonable para la función que utiliza longjmp.

SetJMP se implementa de muchas maneras diferentes, pero esto probablemente tiene algo que ver con la implementación de la ensamblaje para su sistema operativo en particular.

Cuando una función se compila usando __stdcall, los argumentos se almacenan en relación con el puntero de marco. Su implementación puede estar accediendo a los argumentos a SETJMP en relación con dicho puntero para que no tenga que destrozar múltiples registros para salvarles el contexto (ya que esto arruinaría gran parte del punto de SETJMP); Parece que recuerdo que SetJMP se implementa de esta manera en el kernel de Linux.

Por supuesto, si MSVC no genera instrucciones para establecer EBP, entonces esto no funcionará y seguramente causará un bloqueo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top