2011-01-07 19 views
13

Esta es una pregunta inusual, pero aquí va:¿Por qué mi código no se segfault en Windows 7?

En mi código, accidentalmente hago referencia a NULL en algún lugar. Pero en lugar de que la aplicación falle con segfault, parece detener la ejecución de la función actual y simplemente devolver el control a la IU. Esto hace que la depuración sea difícil porque normalmente me gustaría que me avisen del bloqueo para que pueda adjuntar un depurador.

¿Qué podría estar causando esto?

Específicamente, mi código es un controlador ODBC (es decir, una DLL). Mi aplicación de prueba es ODBC Test (odbct32w.exe) que me permite llamar explícitamente a las funciones de la API ODBC en mi DLL. Cuando invoco una de las funciones que tiene una falla de segmentación conocida, en lugar de bloquear la aplicación, la prueba ODBC simplemente devuelve el control a la interfaz de usuario sin imprimir el resultado de la llamada a la función. Luego puedo volver a llamar a cualquier función en mi controlador.

Sé que técnicamente la aplicación llama al administrador del controlador ODBC que carga y llama las funciones en mi controlador. Pero eso no viene al caso ya que mi segfault (o lo que esté sucediendo) hace que la función del administrador del controlador no vuelva tampoco (como lo demuestra la aplicación que no imprime un resultado).

Uno de mis compañeros de trabajo con una máquina similar experimenta el mismo problema mientras que otro no pero no hemos podido determinar ninguna diferencia específica.

+18

Me encanta el título de esta pregunta ... pero no puedo posiblemente * * nave sin errores !! –

+2

Parece que ha proporcionado todo, excepto el código. Quizás el compilador está optimizando el código que no hace nada. –

+3

Supongo que la excepción se está manejando en alguna parte? – EboMike

Respuesta

40

Windows tiene non-portable language extensions (known as "SEH") que le permiten detectar fallas de página y violaciones de segmentación como excepciones.

Hay partes de las bibliotecas del sistema operativo (especialmente dentro del código del sistema operativo que procesa algunos mensajes de ventana, si no recuerdo mal) que tienen un bloque __try y harán que su código continúe ejecutándose incluso ante tales errores catastróficos. Probablemente lo llamen dentro de uno de estos bloques __try. Triste pero cierto.

Salida esta entrada del blog, por ejemplo: The case of the disappearing OnLoad exception – user-mode callback exceptions in x64

Actualización:

me resulta un poco raro el tipo de ideas que están siendo atribuidos a mí en los comentarios. Para el registro:

  • hice no afirmación de que SEH sí mismo es malo.

    Dije que es "no portátil", lo cual es cierto. También afirmé que usar SEH para ignorar STATUS_ACCESS_VIOLATION en el código del modo de usuario es "triste". Estoy de acuerdo con esto. Espero que tuviera el valor de hacer esto en un código nuevo y que estuvieras revisando mi código para que me grites, como si escribiera catch (...) { /* Ignore this! */ }. Es una mala idea. Es especialmente malo para la violación de acceso porque obtener un AV generalmente significa que su proceso está en mal estado y no debe continuar la ejecución.

  • Hice no argumentan que la existencia de SEH significa que debe tragar todos los errores.

    Por supuesto, SEH es un mecanismo general y no tiene la culpa de cada uso idiota de la misma. Lo que dije fue que algunos binarios de Windows tragan STATUS_ACCESS_VIOLATION al llamar a un puntero de función, un hecho real y observable, y que esto es menos que bonito. Tenga en cuenta que pueden tener razones históricas o circunstancias atenuantes para justificar esto. De ahí "triste pero verdadero"."

  • lo hice no inyecte ningún 'retórica de Windows vs Unix' aquí. Una mala idea es una mala idea en cualquier plataforma. Tratando de recuperarse de SIGSEGV en un sistema operativo de tipo Unix sería igualmente vagos.

+2

No llamaría a SEH como extensión de idioma, lo considero más como un servicio proporcionado por el sistema operativo. No estoy seguro de las devoluciones de mensajes de ventana, ¿qué son? ¿Te refieres a WNDPROC? Aunque Windows no es lo mismo que UNIX, ese hecho por sí solo no lo hace inferior. –

+0

@David Heffernan - Sí, quiero decir 'WNDPROC's y no estoy diciendo nada acerca de si la noción de' WNDPROC' hace algo inferior o superior, solo que es una mala idea usar SEH para atrapar 'STATUS_ACCESS_VIOLATION' . Capturar un comportamiento catastrófico, no matar el proceso, y pretender que no pasó nada es categóricamente malo. – asveikau

+0

Parece razonable pero no explica por qué el código se bloqueaba en una máquina pero ocultaba la falla en otra. – Trevor

17

Desreferenciar puntero NULL es un comportamiento indefinido, que puede producir casi cualquier cosa - un seg.fault, una carta al IRS, o un puesto de stackoverflow :)

+11

+1 * publicar en stackoverlow * :) –

+10

¿Está eso en orden ascendente de maldad? :) – EboMike

+3

Esto es 100% correcto, pero en realidad no es una respuesta a esta pregunta específica. – Mordachai

2

Lea sobre los diferentes tipos de controladores de excepciones here - no detectan el mismo tipo de excepciones.

1

Adjunte su depurador a todas las aplicaciones que puedan llamar a su dll, active la función para interrumpir cuando se lanza una excepción no solo no controlada en el menú [depuración] | [excepciones].

ODBC es la mayoría (si no todas) COM como tales excepciones no controladas causarán problemas, que podrían aparecer como salir de la función ODBC extrañamente o tan mal como colgar y nunca volver.

+0

100% de acuerdo: lo que probablemente está sucediendo es que algún código superior en la pila está atrapando la excepción. La forma de encontrar esto es iniciar su aplicación bajo un depurador (o adjuntar un depurador a su aplicación) y permitir la captura de excepciones de primera oportunidad. Debería golpear con bastante facilidad. –

Cuestiones relacionadas