Cómo depurar las infracciones de acceso cuando se ejecuta mi programa fuera del depurador de Visual Studio
Establezca la opción Depuración Just-In-Time y ejecute el programa de forma independiente hasta que se produzca la infracción de acceso. A continuación, en el cuadro de diálogo Infracción de acceso, se puede hacer clic en Cancelar para iniciar el depurador.
Cómo depurar una infracción de acceso de C++
Si se produce una infracción de acceso en una línea de código que desreferencia varios punteros, puede ser difícil averiguar qué puntero produjo la infracción de acceso. En Visual Studio, el cuadro de diálogo de excepción indica explícitamente el puntero que ha provocado la infracción de acceso.
Por ejemplo, con el siguiente código, debería obtener una infracción de acceso:
#include <iostream>
using namespace std;
class ClassC {
public:
void printHello() {
cout << "hello world";
}
};
class ClassB {
public:
ClassC* C;
ClassB() {
C = new ClassC();
}
};
class ClassA {
public:
ClassB* B;
ClassA() {
// Uncomment to fix
// B = new ClassB();
}
};
int main() {
ClassA* A = new ClassA();
A->B->C->printHello();
}
Si ejecuta este código en Visual Studio, verá el cuadro de diálogo de excepción siguiente:
Si no puede determinar por qué el puntero ha provocado una infracción de acceso, realice el seguimiento del código para asegurarse de que el puntero que causa el problema se ha asignado correctamente. Si se pasa como parámetro, asegúrese de que se pasa correctamente y que no está creando accidentalmente una copia superficial. A continuación, compruebe que los valores no se cambian involuntariamente en algún lugar del programa mediante la creación de un punto de interrupción de datos para el puntero en cuestión, para asegurarse de que no se esté modificando en otra parte del programa. Para obtener más información sobre los puntos de interrupción de datos, vea la sección sobre los puntos de interrupción de datos en Using Breakpoints.
Cómo averiguar si los punteros dañan una dirección de memoria
Compruebe si el montón está dañado. La mayoría de los daños en la memoria se deben a que el montón está dañado. Pruebe a usar la utilidad de marcas global (gflags.exe) o pageheap.exe. Vea /windows-hardware/drivers/debugger/gflags-and-pageheap.
Para averiguar dónde se ha modificado la dirección de memoria, haga lo siguiente:
Establezca un punto de interrupción de datos en 0x00408000. Vea Establecer un punto de interrupción de cambio de datos (solo C++ nativo).
Cuando alcance el punto de interrupción, utilice la ventana Memoria para ver el contenido de la memoria a partir de la dirección 0x00408000. Para obtener más información, vea Ventanas de memoria.
Cómo averiguar quién está pasando un valor de parámetro erróneo
Para resolver este problema:
Establezca un punto de interrupción de ubicación al principio de la función.
Haga clic con el botón derecho en el punto de interrupción y seleccione Condición.
En el cuadro de diálogo Condición del punto de interrupción, active la casilla Condición. Vea Puntos de interrupción avanzados.
Escriba una expresión, como
Var==3
, en el cuadro de texto, dondeVar
es el nombre del parámetro que contiene el valor no válido, y3
es el valor no válido que se le ha pasado.Seleccione el botón de radio es True y haga clic en el botón Aceptar.
Ejecute el programa otra vez. El punto de interrupción hace que el programa se detenga al principio de la función cuando el parámetro
Var
sea3
.Utilice la ventana Pila de llamadas para detectar la función que realizó la llamada y navegar hasta su código fuente. Para obtener más información, vea Cómo: usar la ventana Pila de llamadas.
Determinar qué llamada genera el error cuando se llama a una función varias veces
Ejemplo: el programa presenta un error en una llamada a una cierta función, CnvtV
. El programa probablemente llama a esa función unas doscientas veces antes del error. Si se define un punto de interrupción en CnvtV
, el programa se detiene en todas las llamadas a esa función, pero no es eso lo que se pretende. No se sabe qué condiciones hacen que la llamada produzca un error, de modo que no se puede establecer un punto de interrupción condicional. ¿Qué puedo hacer?
Puede establecer un punto de interrupción en la función con el campo Número de llamadas establecido en un valor tan alto que no se pueda alcanzar. En este caso, como la función CnvtV
se invoca unas doscientas veces, asigne a Número de llamadas un valor de 1000 o superior. A continuación, ejecute el programa y espere a que se produzca el error de la llamada. Cuando lo haga, abra la ventana Puntos de interrupción y examine la lista de puntos de interrupción. El punto de interrupción definido sobre CnvtV
aparece seguido del número de llamadas y el número de iteraciones restantes:
CnvtV(int) (no condition) when hit count is equal to 1000 (currently 101)
Ahora sabe que la función produjo un error en la llamada nº 101. Si restablece el punto de interrupción con un número de llamadas de 101 y ejecuta el programa otra vez, éste se detiene en la llamada a CnvtV
que causó el error.
Dónde buscar códigos de error de Win32
El archivo WINERROR.H, situado en el directorio INCLUDE de la instalación predeterminada del sistema, contiene las definiciones de código de error para las funciones de la API Win32.
Puede buscar un código de error escribiendo el código en la ventana Inspección o en el cuadro de diálogo Inspección rápida. Por ejemplo:
0x80000004,hr
Cómo mantener el foco mientras se ejecuta la aplicación paso a paso
Ejemplo: el programa presenta un problema de activación de ventana. Si se ejecuta el programa paso a paso con el depurador, se interfiere con la capacidad de reproducir el problema debido a que el programa pierde el foco. ¿Hay alguna manera de evitar perder el foco?
Si dispone de un segundo equipo, utilice la función de depuración remota. Puede ejecutar el programa en el equipo remoto mientras ejecuta el depurador en el equipo host. Para obtener más información, vea Cómo: seleccionar un equipo remoto.
Cómo depurar funciones de API de Windows
Para establecer un punto de interrupción en una función API de Windows con símbolos de NT cargados, haga lo siguiente:
En el punto de interrupción de la función, escriba el nombre de la función junto con el nombre del archivo DLL en el que se encuentra la función (consulte el operador de contexto). En el código de 32 bits, utilice el formato representativo del nombre de la función. Para establecer un punto de interrupción en MessageBeep, por ejemplo, debe escribir lo siguiente:
{,,USER32.DLL}_MessageBeep@4
Para obtener el nombre representativo, vea Ver nombres representativos.
Puede probar el nombre representativo y verlo en el código del desensamblado. Mientras esté en pausa en la función en el depurador de Visual Studio, haga clic con el botón derecho en dicha función en el editor de código o en la ventana de la pila de llamadas y elija Ir al desensamblado.
En el código de 64 bits, puede utilizar el nombre no representativo.
{,,USER32.DLL}MessageBeep
Pasos siguientes
Puede obtener más información sobre la depuración de código nativo en Visual Studio mediante estos vínculos: