realloc实现导致访问冲突的问题

时间:2011-03-04 18:43:33

标签: c++ c visual-studio-2010 visual-c++

我有一个自定义字符串类,内部是malloc / realloc / free;对于某些字符串附加工作正常,但在某些其他字符串上它将始终失败(小或大分配)。相同的代码在不同的项目上运行良好,尽管它是ANSI构建。

我相信我正确地实现了这一点,但很可能我忽视了一些事情。打开日志后,当我尝试使用“szLog”缓冲区时,会发生错误。这只包含程序文件目录的路径(总共40个字符)。使用没有“日志文件”前缀的相同缓冲区工作正常,因此这是realloc部分的问题。是的,日志确实打开了。

我得到 0xC0000005:访问冲突读取位置0x00660063。仅在使用realloc时(但如前所述,它并不总是失败 - 在这种情况下,当输入szLog时 - 但是其他变量字符串/缓冲区也这样做。)

HeapReAlloc 是realloc.c中的失败函数,errno为22。

我已经删除了评论,试图让帖子尽可能小!任何帮助将不胜感激。

gData.szLogStr 是UString, IsNull 是“ x == NULL ”和 unichar 只是wchar_t

的typedef
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);
    }

这是从主要通道内调用的:

        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 个答案:

答案 0 :(得分:1)

您使用c ++编程,因此请使用newdelete。要“更新”,请分配一个足够大的新内存区域来容纳新字符串,使用正确的值初始化它,然后delete旧字符串。

答案 1 :(得分:0)

什么是str_length()失败时返回?我会追踪muiAlloc的价值,看看你真正想要分配什么。它可能不是一个理智的数字。

你确定szLog中的任何内容都是以null结尾的,并且缓冲区有空间容纳你复制到它的任何内容吗?目前尚不清楚str_copy是否安全。它可能是strncpy()的包装器,它不保证null终止符,但有些人错误地认为它有。