9

我无法在可以显示的较小程序中复制此问题,因此我将用屏幕截图说明问题。

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

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

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

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

如您所见,最初我有一个 return 语句,我将其注释掉以便调试代码段。被注释掉的另一行是获取数组的第一个(也是唯一一个)元素的地址;这条被注释掉的行与它之前的行做同样的事情,即:const char8* address = sm_emptyString.m_Empty8;.

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

在获得地址之前休息

上面,你可以看到我在地址被复制到指针之前就中断了。sm_emptyString下面是这个休息时间的观察窗口值address

在此处输入图像描述

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

在此处输入图像描述

以及相应的观察窗口:

在此处输入图像描述

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

这里发生了什么?我是否在某处覆盖了内存?我该如何调试呢?

编辑:

反汇编(根据调试器,sm_emptyStringis的地址129F184,与反汇编显示的不同 is 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;
  }

我正在使用什么: Windows 7、VC++ 2008、调试版本

4

1 回答 1

2

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

inline const char8* GetEmptyString( char8 )     
{
    static const char8 address[1] = {0};
    return address;
}

编辑:为什么我建议像你的代码那样使用联合是错误的。C99 标准说的一些事情:

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

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

于 2012-09-24T00:51:50.440 回答