Question

Je suis en train d'apporter des améliorations à un programme ancien CV 4 ans de 6,0. La version de débogage va de la ligne de commande, mais pas dans le débogueur: il se bloque avec une violation d'accès à l'intérieur printf (). Si je saute le printf, puis il se bloque dans malloc () (appelé dans fopen ()) et je ne peux pas ignorer cela.

Cela signifie que je ne peux pas courir dans le débogueur et doivent compter sur les anciens printf pour voir ce qui se passe. Cela rend évidemment beaucoup plus difficile.

Toute idée pourquoi printf () et malloc () échouerait lors de l'exécution sous le débogueur du VC? Je ne suis pas bon à ce genre de choses de bas niveau!

Voici la pile d'appel après la violation d'accès:

_heap_alloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 394 + 8 bytes
_nh_malloc_dbg(unsigned int 24, int 0, int 2, const char * 0x0046b3d8 `string', int 225) line 242 + 21 bytes
_malloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 163 + 27 bytes
_lock(int 2) line 225 + 19 bytes
_getstream() line 55 + 7 bytes
_fsopen(const char * 0x00468000 `string', const char * 0x00466280 `string', int 64) line 61 + 5 bytes
fopen(const char * 0x00468000 `string', const char * 0x00466280 `string') line 104 + 15 bytes
open_new_log(const char * 0x00468000 `string') line 66 + 14 bytes
log_open(const char * 0x00468000 `string', int 0) line 106 + 9 bytes
Xlog_open(const char * 0x00468000 `string', int 0) line 51 + 13 bytes
service_start(unsigned long 1, char * * 0x009a0e50) line 3152 + 12 bytes
service_init2(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, char * 0x00466540 `string', unsigned long 1, char * * 0x009a0e50) line 508 + 13 bytes
service_init(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, unsigned long 2, char * * 0x009a0e50) line 548
main(unsigned long 2, char * * 0x009a0e50) line 3131
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817067()

Voici le débogage désassemblage à l'opération qui échoue:

0041EA7E   jmp         _heap_alloc_dbg+2B3h (0041eb23)
0041EA83   mov         edx,dword ptr [_lTotalAlloc (004b4294)]
0041EA89   add         edx,dword ptr [nSize]
0041EA8C   mov         dword ptr [_lTotalAlloc (004b4294)],edx
0041EA92   mov         eax,[_lCurAlloc (004b429c)]
0041EA97   add         eax,dword ptr [nSize]
0041EA9A   mov         [_lCurAlloc (004b429c)],eax
0041EA9F   mov         ecx,dword ptr [_lCurAlloc (004b429c)]
0041EAA5   cmp         ecx,dword ptr [_lMaxAlloc (004b42a0)]
0041EAAB   jbe         _heap_alloc_dbg+249h (0041eab9)
0041EAAD   mov         edx,dword ptr [_lCurAlloc (004b429c)]
0041EAB3   mov         dword ptr [_lMaxAlloc (004b42a0)],edx
0041EAB9   cmp         dword ptr [_pFirstBlock (004b4298)],0
0041EAC0   je          _heap_alloc_dbg+25Fh (0041eacf)
0041EAC2   mov         eax,[_pFirstBlock (004b4298)]
0041EAC7   mov         ecx,dword ptr [pHead]
0041EACA   mov         dword ptr [eax+4],ecx

Voici notre source qui appelle fopen () et échoue dans malloc ()

FILE *open_new_log( const char *logfile )
{
    FILE *fp;
    int retry = 0;

    while( ( fp = fopen( logfile, "w" ) ) == NULL && ++retry < 300 )
        Sleep( 1000 );

    return( fp );
}

L'erreur que je reçois est

Unhandled exception inPISCOOP.exe: 0xC00000005: Access Violation

Cordialement,

--- Alistair.

Était-ce utile?

La solution

Vous pouvez utiliser _CrtSetDbgFlag() pour permettre un tas de techniques de débogage tas utiles. Il y a une foule d'autres fonctions de débogage CRT disponible qui devrait vous aider à traquer où votre problème.

Autres conseils

Lorsqu'il est exécuté à partir du débogueur, un tas différent est utilisé; cela est appelé le tas de débogage . Cela a un comportement différent du tas utilisé en dehors du débogueur, et est là pour vous aider à attraper des problèmes comme celui-ci.

Notez que le « tas de débogage » Win32 est distincte de la « tas de débogage » du VC; les deux sont destinés à faire plus ou moins la même chose, cependant. Voir cet article qui décrit la différence de comportement lorsque vous exécutez l'application sous le débogueur.

Dans ce cas, vous avez probablement corrompu le tas avant d'appeler cette fonction, soit en écrivant à l'extrémité ou hors le début d'un bloc de tas.

Le plus d'approches (à condition que votre application n'utilise pas la mémoire trop extensive) est d'activer le contrôle de tas pleine page (qui place ce qu'on appelle la page de garde après la page de la mémoire de votre allocation est fournie à partir, ce qui, à son tour, localiser l'endroit exact dans votre code où la corruption a lieu).

Étant donné que vous avez outils de débogage de Windows à portée de main, exécutez la commande gflags suivantes pour configurer tas pleine page:

gflags[.exe] /p /enable yourapp.exe /full

Note, vous devez fournir le nom exécutable seul (à savoir sans préfixe de chemin!)
Ensuite, exécutez juste sous le débogueur - il rompre avec la première tentative de corrompre le Tas. La différence ici est que tas corruptions sont le plus souvent retardés défauts qui se manifestent plus tard, quand un (peut-être) opération de tas valide est en vigueur.

Note, aussi:

gflags[.exe] /p /enable yourapp.exe /full /backwards

placera en outre une page de garde avant votre allocation.

Exécution avec commutateur / p seul affiche les options de page tas actuellement en vigueur.

Vous pouvez avoir un bug de corruption du tas. Votre application peut avoir corrompu le tas avant open_new_log() est appelé.

Je soupçonne que jmattias a raison. La cause racine du problème est probablement un autre endroit que celui où il se bloque.

Beaucoup de choses peuvent causer une corruption du tas.

  • écrit après la fin (ou au début) du bloc de mémoire qui a été allouée.
  • libérant un pointeur deux fois, ou en libérant un pointeur qui n'a pas été attribué.
  • multithreading votre programme et la liaison avec le seul thread (pas thread-safe) RTL.
  • allocation de mémoire d'un tas et de libérer sur un autre tas.
  • etc., Etc.,

Puisque vous utilisez Visual C ++, vous pouvez utiliser la fonction _CrtSetDbgFlag () du tas de débogage pour activer la vérification des erreurs. Vous pouvez le configurer pour vérifier l'intégrité du tas sur chaque appel à malloc ou libre. Qui se déroulera très lentement, mais il faut mettre le doigt sur le bug pour vous.

Rechercher _CrtSetDbgFlag dans le compilateur docs.

Je soupçonne qu'il ya une DLL compilée avec une version différente du runtime C ++ que le reste de l'application. Cela se traduira souvent dans « la mémoire à l'adresse XXX ne pouvait être « lire »/ « écrite » » violations.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top