Problem with realloc implementation resulting in Access violation
I have a custom string class that malloc/realloc/free's internally; For certain strings appending works fine, but on certain others it will always fail (small or large allocations). The same code worked fine on a different project, although it was an ANSI build.
I believe I'm implementing this correctly, but most likely I've overlooked something. The error occurs when I attempt to utilize the "szLog" buffer once the log has been opened. This simply contains the path to the program files directory (40 characters total). Using this same buffer without the "Log file '" prefix works fine, so it's an issue with the realloc section. And yes, the log does open properly.
I get 0xC0000005: Access violation reading location 0x00660063. only when realloc is used (but as previously stated, it doesn't always fail - in this situation, when szLog is input - but other variable strings/buffers do it too).
HeapReAlloc is the failing function inside realloc.c, errno being 22.
I've stripped the comments to try and keep the post as small as possible! Any help would be much appreciated.
gData.szLogStr is a UString, IsNull is a definition for "x == NULL" and unichar is simply a typedef for 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);
}
and this being called from within main via:
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);
}
You are programming in c++, so use new
and delete
. To 'renew', allocate a new memory area large enough to hold the new string, initialize it with the correct values and then delete
the old string.
What is str_length() returning when it fails? I'd trace the value of muiAlloc and see what you're actually trying to allocate. It may not be a sane number.
Are you certain that whatever's in szLog is null-terminated, and that the buffer has room for whatever you're copying into it? It's not clear if str_copy is safe or not. It may be a wrapper around strncpy(), which does not guarantee a null terminator, but some people mistakenly assume it does.
精彩评论