简单赋值时内存分配错误

Aas*_*bab -5 c++ unicode mfc tchar

为了从给定路径获取父目录,我有以下代码。注:为size_t是一种类型定义unsigned int类型

/****************************************************
This function takes a full path to a file, and returns
the directory path by returning the string up to the last backslash.

Author: Aashish Bharadwaj
*****************************************************/
_TCHAR* GetDirectoryFromPath(const _TCHAR* path)
{
   size_t size = _tcslen(path);
   size_t lastBackslash = 0;
   for (size_t i = 0; i < size; i++)
   {
      if (path[i] == '\\')
      {
         lastBackslash = i;
      }
   }

   _TCHAR* dirPath = new _TCHAR();
   size_t i;
   for (i = 0; i <= lastBackslash; i++)
   {
      dirPath[i] = path[i];
   }
   dirPath[i + 1] = '\0';  //THIS IS VERY NECESSARY! Otherwise, a bunch of garbage is appended to the character array sometimes.

   return dirPath;
}
Run Code Online (Sandbox Code Playgroud)

问题是有时它会在它返回的字符串末尾附加一个奇怪的“@”符号。在此处输入图片说明

我想知道是否有人知道这是什么以及为什么这样做。

Rem*_*eau 5

问题是您只分配了 1 个 TCHAR,然后您写入的内容超过了您分配的内存块的末尾。您的代码具有未定义的行为

您需要使用new _TCHAR[...]而不是new _TCHAR().

您也没有处理找不到反斜杠的情况。在这种情况下,lastBackslash即使第一个字符不是反斜杠,也是 0。你不是在检查这种可能性。并且因为您的循环使用的是<=而不是<,所以它最终会在不应该复制第一个字符时复制它。

尝试更像这样的事情:

const size_t c_invalid_index = (size_t) -1;

_TCHAR* GetDirectoryFromPath(const _TCHAR* path)
{
    size_t lastBackslash = c_invalid_index;

    size_t size = _tcslen(path);
    for (size_t i = 0; i < size; ++i)
    {
        if (path[i] == _T('\\'))
        {
            lastBackslash = i;
        }
    }

    if (lastBackslash == c_invalid_index)
        return NULL;

    _TCHAR* dirPath = new _TCHAR[lastBackslash + 2];
    for (size_t i = 0; i <= lastBackslash; ++i)
    {
        dirPath[i] = path[i];
    }
    dirPath[lastBackslash + 1] = _T('\0');

    return dirPath;
}
Run Code Online (Sandbox Code Playgroud)

或者:

_TCHAR* GetDirectoryFromPath(const _TCHAR* path)
{
    const _TCHAR *lastBackslash = NULL;

    size_t size = _tcslen(path);
    for (size_t i = 0; i < size; ++i)
    {
        if (path[i] == _T('\\'))
        {
            lastBackslash = &path[i];
        }
    }

    if (!lastBackslash)
        return NULL;

    size = (lastBackslash - path) + 1;

    _TCHAR* dirPath = new _TCHAR[size + 1];
    for (size_t i = 0; i < size; ++i)
    {
        dirPath[i] = path[i];
    }
    dirPath[size] = _T('\0');

    return dirPath;
}
Run Code Online (Sandbox Code Playgroud)

话虽如此,您真的不应该像这样使用原始字符串指针。使用它会更安全、更干净std::basic_string<_TCHAR>(如果不是std::stringstd::wstringstd::u16stringstd::u32string在 C++11 及更高版本中),例如:

#include <string>

typedef std::basic_string<_TCHAR> tstring;

...

tstring GetDirectoryFromPath(const tstring &path)
{
    tstring::size_type pos = path.find_last_of(_T('\\'));
    if (pos == tstring::npos)
        return tstring();
    return path.substr(0, pos+1);
}
Run Code Online (Sandbox Code Playgroud)