代码之家  ›  专栏  ›  技术社区  ›  Aashishkebab

简单赋值时内存分配错误

  •  -5
  • Aashishkebab  · 技术社区  · 8 年前

    为了从给定路径获取父目录,我有以下代码。 注: 尺寸 是一个 类型定义 对于 无符号整型 .

    /****************************************************
    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;
    }
    

    有时 它会在返回的字符串末尾附加一个看起来奇怪的“@”符号。 enter image description here

    我想知道是否有人知道这是什么,为什么会这样做。

    1 回复  |  直到 8 年前
        1
  •  5
  •   Remy Lebeau    8 年前

    问题是你正在分配 只有一个 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;
    }
    

    或者:

    _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;
    }
    

    话虽如此,您真的不应该使用这样的原始字符串指针。使用起来会更安全、更清洁 std::basic_string<_TCHAR> 相反(如果不是的话) std::string 或 std::wstring 或 std::u16string 或 std::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);
    }
    
    推荐文章