Проблема с реализацией realloc, приводящая к нарушению прав доступа - PullRequest
0 голосов
/ 04 марта 2011

У меня есть собственный строковый класс, который внутри malloc / realloc / free;Для определенных строк добавление работает нормально, но для некоторых других оно будет всегда терпеть неудачу (небольшие или большие выделения).Тот же код отлично работал в другом проекте, хотя это была сборка ANSI.

Я полагаю, что я правильно это реализую, но, скорее всего, я что-то упустил.Ошибка возникает, когда я пытаюсь использовать буфер "szLog" после открытия журнала.Он просто содержит путь к каталогу программных файлов (всего 40 символов).Использование этого же буфера без префикса «Файл журнала» работает нормально, так что это проблема с разделом realloc.И да, журнал действительно открывается правильно.

Я получаю 0xC0000005: Место чтения нарушения доступа 0x00660063. только при использовании realloc (но, как уже было сказано, не всегда происходит сбой - вэта ситуация, когда вводится szLog - но другие переменные строки / буферы тоже делают это).

HeapReAlloc - это сбойная функция внутри realloc.c, ошибочно равная 22.

Я убрал комментарии, чтобы пост был как можно меньше!Любая помощь будет принята с благодарностью.

gData.szLogStr - это строка UST, IsNull - это определение " x == NULL " и unichar - это просто typedef для wchar_t

class UString : public Object
{
private:
    unichar*    mpsz;
    unichar*    mpszPrev;
    UINT        muiAlloc;
    UINT        muiLen;
public:
    ... other functions ...

    UString& operator << (const unichar* pszAdd)
    {
        if ( IsNull(pszAdd) )
            return (*this);
        if ( IsNull(mpsz) )
        {
            muiAlloc = ((str_length(pszAdd)+1) * sizeof(unichar));
            if ( IsNull((mpsz = static_cast<unichar*>(malloc(muiAlloc)))) )
            {
                SETLASTERROR(ERR_NOT_ENOUGH_MEMORY);
                muiAlloc = 0;
                return (*this);
            }
            mpszPrev = mpsz;
            muiLen = str_copy(mpsz, pszAdd, muiAlloc);
        }
        else
        {
            UINT    uiNewAlloc = (muiAlloc + (str_length(pszAdd) * sizeof(unichar)));

            if ( muiAlloc < uiNewAlloc )
            {
                uiNewAlloc *= 2;

                /* Fails */
                if ( IsNull((mpsz = static_cast<unichar*>(realloc(mpsz, uiNewAlloc)))) )
                {
                    SETLASTERROR(ERR_NOT_ENOUGH_MEMORY);
                    mpsz = mpszPrev;
                    return (*this);
                }
                mpszPrev = mpsz;
                muiAlloc = uiNewAlloc;
            }
            muiLen = str_append(mpsz, pszAdd, muiAlloc);
        }
        return (*this);
    }

, который вызывается из main через:

        UString     szConf;
        unichar     szLog[MAX_LEN_GENERIC];

        szConf << ppszCmdline[0];
        szConf.replace(_T(".exe"), _T(".cfg"));
        if ( GetPrivateProfileString(_T("Application"), _T("LogFile"), NULL, szLog, sizeofbuf(szLog), szConf.str()) == 0 )
        {
            UINT    uiLen = str_copy(szLog, szConf.str(), sizeofbuf(szLog)); 
            szLog[uiLen-3] = 'l';
            szLog[uiLen-2] = 'o';
            szLog[uiLen-1] = 'g';
        }

        if ( ApplicationLog::Instance().Open(szLog, CREATE_ALWAYS) )
        {
            gData.szLogStr.clear();
            /* Erroring call */
            gData.szLogStr << _T("Log file '") << szLog << _T("' opened");
            APP_LOG(LL_WriteAlways, NULL, gData.szLogStr);
            ObjMgr::Instance().DumpObjects(LogDumpedObjects);
        }

Ответы [ 2 ]

1 голос
/ 04 марта 2011

Вы программируете на c ++, поэтому используйте new и delete.Чтобы «обновить», выделите новую область памяти, достаточно большую, чтобы вместить новую строку, инициализируйте ее правильными значениями и затем delete старая строка.

0 голосов
/ 04 марта 2011

Что возвращает str_length () при сбое?Я бы проследил значение muiAlloc и увидел, что вы на самом деле пытаетесь выделить.Это может быть не вменяемое число.

Вы уверены, что все, что находится в szLog, заканчивается нулем, и что в буфере есть место для всего, что вы копируете в него?Не ясно, безопасен ли str_copy или нет.Это может быть обертка вокруг strncpy (), которая не гарантирует нулевого терминатора, но некоторые люди ошибочно полагают, что это так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...