Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copying the address of a static union member gives the incorrect address

I cannot replicate this problem in a smaller program that I can show so I will illustrate the question with screenshots.

I have a class that declares a union and a static member of the 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 };

I then have a function that returns the address of the string. For debugging purposes, I have added the variable address so that I can add it to the watch window. Here is the function (T here is a char8 where char8 is a typedef for 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;
  }

As you can see, initially I had the one return statement, which I commented out so that I can debug the snippet. The other line that is commented out is taking the address of the first (and only) element of the array; this commented out line does the same thing as the line previous to it, which is: const char8* address = sm_emptyString.m_Empty8;.

The program crashes because I am not getting the correct address by the above function and this has stumped me. Below I will start screenshots of my debugging session:

Break before getting address

Above, you can see that I am breaking just before the address is copied to the pointer. Below is the watch window values for sm_emptyString and address at this break.

enter image description here

So far, nothing special. Below is the screenshot after stepping over one line of code.

enter image description here

And the corresponding watch window:

enter image description here

As you can see, the value copied to address is wrong. Another thing to note is that this function gets called a few times and the copy of the static variable address to address is correct. When the address is incorrect and is returned by the function, my program crashes (because of the assumptions about the address later on in the program).

What is happening here? Am I over-writing memory somewhere? How do I go about debugging this?

EDIT:

The disassembly (according to the debugger, the address of sm_emptyString is 129F184, different than what the disassembly shows which 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;
  }

What I am using: Windows 7, VC++ 2008, Debug build

like image 972
Samaursa Avatar asked Sep 23 '12 23:09

Samaursa


1 Answers

Use a function? The empty string you need has nothing to do with StringBase<T> nor its state nor its template argument.

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

EDIT: Why i suggest it is that using union like your code uses is wrong. Some things that C99 standard say:

  • 6.2.5p20, union has an overlapping set of member objects
  • 6.7.2.1p14, the value of at most one of the members can be stored in a union object at any time
  • Annex J.1 the value of a union member other than the last one stored into is unspecified.

Same goes with C++, just don't have the standard handy now. So you can not use union to store 3 strings at same place at same time. While I am not sure what actually causes the problems, it is likely totally elsewhere, you should get rid of such questionable constructs.

like image 180
Öö Tiib Avatar answered Oct 28 '22 05:10

Öö Tiib