(Visual C ++) Динамическая память распределения не является действительным указателем после удаления указателя - PullRequest
0 голосов
/ 12 января 2012

У меня есть программа, когда я нажимаю кнопку «Загрузить», программа создает новый поток для загрузки веб-страниц и сохраняет его в переменной динамического размещения 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
}

Ответы [ 2 ]

3 голосов
/ 12 января 2012

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

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

Выделите sqlSize количество байтов, а затем очистите первые четыре из них, поскольку sizeof (sql) равно 4. Итак, если sqlSize меньше 4, вы выделяете менее 4 байтов, а затем обнуляете 4 байта. портит память. Что вам нужно:

    ZeroMemory(sql,sqlSize);

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

1 голос
/ 12 января 2012

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

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

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

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

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

...