Pregunta

Estoy trabajando en un juego y actualmente estoy trabajando en la parte que maneja la entrada. Aquí hay tres clases involucradas, está la clase ProjectInstance que inicia el nivel y demás, hay un GameController que manejará la entrada, y una PlayerEntity el cual será influenciado por los controles según lo determinado por el GameController . Al comenzar el nivel, ProjectInstance crea el GameController y llamará a su método EvaluateControls en el método Step, que se llama dentro del bucle del juego. El método EvaluateControls se parece un poco a esto:

void CGameController::EvaluateControls(CInputBindings *pib) {
    // if no player yet
    if (gc_ppePlayer == NULL) {
        // create it
        Handle<CPlayerEntityProperties> hep = memNew(CPlayerEntityProperties);
        gc_ppePlayer = (CPlayerEntity *)hep->SpawnEntity();
        memDelete((CPlayerEntityProperties *)hep);
        ASSERT(gc_ppePlayer != NULL);
        return;
    }

    // handles controls here
}

Esta función se llama correctamente y la afirmación nunca se activa. Sin embargo, cada vez que se llama a esta función, gc_ppePlayer se establece en NULL. Como puede ver, no es una variable local que está fuera del alcance. El único lugar donde gc_ppePlayer se puede establecer en NULL es en el constructor o posiblemente en el destructor, ninguno de los cuales se llama entre las llamadas a EvaluateControls . Al depurar, gc_ppePlayer recibe un valor correcto y esperado antes de la devolución. Cuando presiono F10 una vez más y el cursor está en la llave de cierre, el valor cambia a 0xffffffff. Estoy perdido aquí, ¿cómo puede pasar esto? ¿Alguien?

¿Fue útil?

Solución

¿Está depurando una versión o configuración de depuración? En la configuración de compilación de la versión, lo que se ve en el depurador no siempre es cierto. Se realizan optimizaciones, y esto puede hacer que la ventana de visualización muestre valores extravagantes como los que está viendo.

¿Realmente estás viendo la activación de ASSERT? Los ASSERT normalmente se compilan a partir de las versiones de la versión, por lo que supongo que está depurando una versión de la versión, por lo que ASSERT no está haciendo que la aplicación finalice.

Recomendaría compilar una versión de depuración del software y luego ver si gc_ppePlayer es realmente NULL. Si realmente lo es, tal vez esté viendo algún tipo de corrupción en el almacenamiento de memoria en el que se anula este puntero. Pero si se tratara de corrupción de memoria, generalmente sería mucho menos determinista de lo que está describiendo.

Además, el uso de valores de punteros globales como este generalmente se considera una mala práctica. Vea si puede reemplazar esto con una clase singleton si es realmente un objeto único y necesita ser accesible globalmente.

Otros consejos

establezca un punto de observación en gc_ppePlayer == NULL cuando el valor de esa expresión cambie (a NULL o desde NULL) el depurador le indicará exactamente dónde ocurrió.

Intenta eso y ve que pasa. Busque cadenas no terminadas o una copia de mempcy en la memoria que sea demasiado pequeña, etc ... por lo general, esa es la causa del problema de que las variables globales / de pila se sobrescriban aleatoriamente.

Para agregar un punto de control en VS2005 (instrucciones por brone)

  
      
  1. Ir a la ventana de puntos de interrupción
  2.   
  3. Haz clic en Nuevo,
  4.   
  5. Haga clic en Punto de interrupción de datos. Entrar
  6.   
  7. & amp; gc_ppePlayer en el cuadro de Dirección, deja   otros valores solos.
  8.   
  9. Entonces corre.
  10.   
     

Cuando gc_ppePlayer cambia,   punto de quiebre       será golpeado. & # 8211; brone

Mi primer pensamiento es decir que SpawnEntity () está devolviendo un puntero a un miembro interno que se está eliminando " " cuando se llama a memDelete () No me queda claro cuándo el puntero está establecido en 0xffffffff, pero si ocurre durante la llamada a memDelete (), esto explica por qué su ASSERT no se está disparando - 0xffffffff no es lo mismo que NULL.

¿Cuánto tiempo ha pasado desde que has reconstruido la base de código completa? He visto problemas de memoria como este de vez en cuando que se solucionan simplemente reconstruyendo la solución completa.

¿Ha intentado dar un paso hacia (F11) en lugar de pasar sobre (F10) al final de la función? Si bien su ejemplo no muestra ninguna variable local, tal vez haya omitido algunas por simplicidad. Si es así, F11 (con suerte) entrará en los destructores para cualquiera de esas variables, permitiéndole ver si una de ellas está causando el problema.

Tienes un " fandango en el núcleo. "

La inicialización dinámica está sobrescribiendo varios bits (sic) de memoria.

Directa o indirectamente, el global se está sobrescribiendo. ¿Dónde está el global en la memoria en relación con el montón?

corte en binario la porción dinámicamente inicializada hasta que el problema desaparezca. (comentar de manera recursiva la mitad de una vez)

Dependiendo de la plataforma en la que se encuentre, existen herramientas (gratuitas o de pago) que pueden resolver rápidamente este tipo de problema de memoria.

Fuera de la parte superior de mi cabeza:

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