(Visual C++) Память динамического выделения не является допустимым указателем после удаления указателя

StackOverflow https://stackoverflow.com/questions/8834906

Вопрос

У меня есть программа, когда я нажимаю кнопку «Загрузить», программа создает новый поток для загрузки веб-страниц и сохраняет его в динамическом размещении. char* переменная.

Но теперь я нажимаю «Загрузить», программа показывает следующую информацию:

---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!

Program: d:\dev\debug\test.exe
File: dbgheap.c
Line: 1279

Expression: _CrtIsValidHeapPointer(pUserData)

Кажется, проблема связана с проблемой выделения или освобождения кучи.

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 функция:

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
}
Это было полезно?

Решение

Следующие инструкции:

    sql = new char[sqlSize];
    ZeroMemory(sql,sizeof(sql));

Выделите количество байтов, а затем очистите первые четыре из них, поскольку Sizeof (SQL) равен 4. Так что, если SQLSize меньше 4, вы распределяете менее 4 байтов, а затем вы нуждаетесь в 4 байтах, таким образом, искажаясь. Память. Вам нужно:

    ZeroMemory(sql,sqlSize);

Также: если _ttoi(str) Выйдет из строя, вы не распределяете буфер, но вы возвращаете его, и я предполагаю, что вы приступите к тому, чтобы попытаться освободить его. Это, вероятно, причина неверного исключения указателя.

Другие советы

Это результат переполнения памяти.Вы записали часть памяти, которая находится за пределами выделенного диапазона.

Что-то вроде:

char *buf = new char[4];
buf[4]=23;    // actual error
delete[] buf; // runtime error (Debug Assertion Fail)

вероятно, выдаст такую ​​ошибку.

Это будет трудно обнаружить в большой программе, поскольку ошибка подтверждения отладки происходит тогда, когда возникает фактическая ошибка.Я бы предложил использовать некоторые инструменты, такие как Верификатор приложений чтобы следить за своей памятью, будет ли программа работать.Application Verifier остановит программу при возникновении неисправности памяти.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top