复制静态联合成员的地址会给出错误的地址

Sam*_*rsa 9 c++ memory pointers

我无法在一个我能展示的小程序中复制这个问题所以我将用截图来说明问题.

我有一个声明union和union的静态成员的类:

class 
{ 
/* rest of the class */

    union EmptyString
    {
      char8   m_Empty8[1];
      uchar8  m_EmptyU8[1];
      char32  m_Empty32[1];
    };

    static const EmptyString sm_emptyString;
};

  // Definition
  template <typename T>
  const typename StringBase<T>::EmptyString 
    StringBase<T>::sm_emptyString = { 0 };
Run Code Online (Sandbox Code Playgroud)

然后我有一个函数返回字符串的地址.出于调试目的,我添加了变量,address以便将其添加到监视窗口.下面是函数(T这里是一个char8地方char8是一个typedef char):

  template <typename T>
  const char8* StringBase<T>::GetEmptyString( char8 )
  {
    const char8* address = sm_emptyString.m_Empty8;
    //const char8* address = &(sm_emptyString.m_Empty8[0]);
    return address;
    //return sm_emptyString.m_Empty8;
  }
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,最初我有一个return语句,我已经注释掉了,以便我可以调试代码片段.注释掉的另一行是获取数组的第一个(也是唯一的)元素的地址; 这个注释掉的行与之前的行相同,即:const char8* address = sm_emptyString.m_Empty8;.

程序崩溃是因为我没有通过上面的函数得到正确的地址,这让我很难过.下面我将开始调试会话的屏幕截图:

在获得地址前休息

上面,你可以看到我在地址被复制到指针之前就打破了.以下是监视窗口中值sm_emptyString,并address在此休息.

在此输入图像描述

到目前为止,没什么特别的 下面是踩过一行代码后的屏幕截图.

在此输入图像描述

和相应的观察窗口:

在此输入图像描述

如您所见,复制到的值address是错误的.另外需要注意的是,此函数被调用几次,静态变量address的副本address是正确的.当地址不正确并由函数返回时,我的程序崩溃(因为程序中稍后对地址的假设).

这里发生了什么?我在某处写过记忆吗?我该如何调试呢?

编辑:

反汇编(根据调试器,地址sm_emptyString129F184,与反汇编显示的不同128F134):

template <typename T>
  const char8* StringBase<T>::GetEmptyString( char8 )
  {
0119B850  push        ebp  
0119B851  mov         ebp,esp 
0119B853  push        ecx  
0119B854  mov         dword ptr [ebp-4],0CCCCCCCCh 
    const char8* address = sm_emptyString.m_Empty8;
0119B85B  mov         dword ptr [address],offset StringBase<char>::sm_emptyString (128F134h) 
    //const char8* address = &(sm_emptyString.m_Empty8[0]);
    return address;
0119B862  mov         eax,dword ptr [address] 
    //return sm_emptyString.m_Empty8;
  }
Run Code Online (Sandbox Code Playgroud)

我正在使用的是: Windows 7,VC++ 2008,Debug build

Öö *_*iib 2

使用函数?StringBase<T>您需要的空字符串与其状态或模板参数无关。

inline const char8* GetEmptyString( char8 )     
{
    static const char8 address[1] = {0};
    return address;
}
Run Code Online (Sandbox Code Playgroud)

编辑:为什么我建议是像您的代码使用的那样使用联合是错误的。C99 标准规定的一些内容:

  • 6.2.5p20,union 有一组重叠的成员对象
  • 6.7.2.1p14,联合对象中任意时刻最多可以存储一个成员的值
  • 附件 J.1 除最后一个存储的联合成员的值未指定。

C++ 也是如此,只是现在没有方便的标准。所以你不能使用 union 同时在同一位置存储 3 个字符串。虽然我不确定到底是什么导致了问题,但很可能完全在其他地方,你应该摆脱这些有问题的构造。