(Visual C ++) Memoria di allocazione dinamica non un puntatore valido dopo l'eliminazione del puntatore
-
27-10-2019 - |
Domanda
Ho un programma, quando faccio clic sul pulsante "Download", Crea un nuovo thread per scaricare le pagine Web e archivialo in un'allocazione dinamica char*
variabile.
Ma ora faccio clic su "Download", il programma mostra le seguenti informazioni:
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!
Program: d:\dev\debug\test.exe
File: dbgheap.c
Line: 1279
Expression: _CrtIsValidHeapPointer(pUserData)
Sembra che il problema sia correlato all'allocazione del heap o al problema delle relazioni.
void SomeClass::get()
{
buf = this->download(url);
while (some condition)
{
......
......
bufContent = this->download(url);
......
......
sql = new char[sqlSize];
ZeroMemory(sql,sqlSize);
sql_utf8 = new char[sqlSize*2];
ZeroMemory(sql_utf8,sqlSize*2);
......
......
delete[] bufContent;bufContent=NULL;
delete[] sql;
delete[] sql_utf8;
}
delete[] buf; buf=NULL;//debug run to here, get Assertion Failed error
}
download
funzione :
char* SomeClass::download(TCHAR* url)
{
char * pBuf = NULL ;
int nBufLen = 0 ;
TRY
{
// connection
CInternetSession sess ;
sess.SetOption (INTERNET_OPTION_CONNECT_TIMEOUT, 30 * 1000) ;
sess.SetOption (INTERNET_OPTION_CONNECT_BACKOFF, 1000) ;
sess.SetOption (INTERNET_OPTION_CONNECT_RETRIES, 1) ;
DWORD dwFlag = INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD ;
CHttpFile * pF = (CHttpFile*)sess.OpenURL(url, 1, dwFlag); ASSERT(pF);
if (!pF)
{AfxThrowInternetException(1);}
// connection status
CString str ;
pF->QueryInfo (HTTP_QUERY_STATUS_CODE, str) ;
if (str != _T("200"))
{
pF->Close() ;
delete pF ;
AfxThrowInternetException(1);
}
// start QzoneBlog
int nLen,nLenCopy;
pF->QueryInfo (HTTP_QUERY_CONTENT_LENGTH, str) ; // file's length
if (_ttoi(str))
{
// know file's size
nLenCopy = nLen = (nBufLen = _ttoi(str)) ;
char * p = (pBuf = new char[nLen+8]) ;
ZeroMemory (p, nLen+8) ;
while (TRUE)
{
int n = pF->Read (p, (nLen < 1024) ? nLen : 1024) ;
if (n <= 0)
break ; // success exit
p += n ; nLen -= n ;
}
// interrupted
if (nLen != 0)
{
//delete[] pBuf; pBuf=NULL;
nBufLen = 0 ;
}
}
pF->Close() ;
delete pF ;
return pBuf;
}
CATCH_ALL(e) {
return 0;
}
END_CATCH_ALL
}
Soluzione
Le seguenti istruzioni:
sql = new char[sqlSize];
ZeroMemory(sql,sizeof(sql));
Allocare il numero di byte sqlsize, quindi cancella i primi quattro, poiché sizeof (sql) è 4. Quindi, se sqlsize è inferiore a 4, stai assegnando meno di 4 byte, e poi stai zero 4 byte memoria. Ciò di cui hai bisogno è:
ZeroMemory(sql,sqlSize);
Inoltre: se _ttoi(str)
fallisce, non allochi un buffer, ma lo restituisci e presumo che tu procedi per provare a liberarlo. Questa è probabilmente la causa l'eccezione del puntatore non valido.
Altri suggerimenti
Questo è il risultato del superamento della memoria. Hai scritto su un po 'di memoria che non è nella gamma allocata.
Qualcosa di simile a:
char *buf = new char[4];
buf[4]=23; // actual error
delete[] buf; // runtime error (Debug Assertion Fail)
Probabilmente genererà tale errore.
Sarà difficile individuare in un grande programma, poiché l'asserzione di debug non si verifica quando si verifica l'errore effettivo. Suggerirei di usare alcuni strumenti come Verificatore dell'applicazione Per tenere un orologio in tua memoria, il programma è in esecuzione. Il verificatore dell'applicazione interromperà il programma ogni volta che c'è un errore di memoria.