Question

I have a templated union type NodeType. The problem is that upon assignement of its variable field are not set properly and when subsequently accessed the contain garbage values. Specifically, the problem occurs with _field1 and _field2 - see the main.

#include <cstdlib>
#include <iostream>

using namespace std;


        template <class T>
        struct structExampleType                
        {
          T _structField;
          typedef structExampleType<T>* pointerStructExample;
        };


         enum TYPE_tag
         {FIELD1_tag, FIELD2_tag} TYPE_tag; 

          template <class T>//, class P>
          union NodeType
          {
           enum TYPE_tag _nodeType_tag;
           char _field1;
           typename structExampleType<T>::pointerStructExample _field2;

           NodeType(){_field2=0;}

           NodeType(enum TYPE_tag nodeType_tag, char _charField)
           {
            _nodeType_tag=nodeType_tag;
            _field1=_charField;
            //_field2=0;
           }  

           NodeType(enum TYPE_tag nodeType_tag, typename structExampleType<T>::pointerStructExample pointer)
           {
            _nodeType_tag=nodeType_tag;
            _field2=pointer;
            //_field1='-';
           }          

          };







int main(int argc, char *argv[])
{
    NodeType<int> node1, node2;
    structExampleType<int>* structExamplePointer;

    structExamplePointer=new structExampleType<int>();

    structExamplePointer->_structField=100;
//    structExamplePointer->_field2=structExamplePointer;

    node1=NodeType<int>(FIELD1_tag,'-');
    node2=NodeType<int>(FIELD2_tag,structExamplePointer);    


    cout<<endl<<"node1: ";    
    if (node1._nodeType_tag==FIELD1_tag)
    {cout<<node1._field1<<endl;}
    else
    {cout<<node1._field2<<endl;}        


    cout<<endl<<"node2: ";
    if (node2._nodeType_tag==FIELD2_tag)
    {cout<<node2._field1<<endl;}
    else
    {
        cout<<node2._field2<<endl;
        cout<<(node2._field2)->_structField<<endl;
    }  



    system("PAUSE");
    return EXIT_SUCCESS;
}

What can be the issue? Thanks in advance for your time.

Was it helpful?

Solution

In main you have these two lines:

structExampleType<int>* structExamplePointer;

structExamplePointer->_structField=100;

Remember that local variables are not initialized unless they have a default constructor (which pointers do not have), so in the second you dereference the uninitialized pointer structExamplePointer, leading to undefined behavior.

You also seem to misunderstand the purpose of union, as you try to set multiple fields. In a union all fields share the same space, so when writing to one member then all members are changed. Only the last written to member is valid. Trying to use other fields may again lead to undefined behavior.


If you need to have a "tag" field and other data, a structure containing the tag and the union data should be your choice:

struct NodeType
{
    enum TAG_Type
    {
        FIELD1,
        FIELD2
    } type;

    union
    {
        char field1;
        struct some_struct* field2;
    }
};

OTHER TIPS

With a union the members try to occupy the same space in memory so your constructor is causing the problem by assigning to each of the members and overwriting each other.

The union is only as big as necessary to hold its largest data member. The other data members are allocated in the same bytes as part of that largest member.

What you actually have here is not a union of field1 and field2, but rather a union of { tag, field1, field2 }. That's why you see garbage. Union is still a single memory area, but you set it three times over in your construction logic.

You might start with simpler cases and read some documentation, e.g., http://msdn.microsoft.com/en-us/library/5dxy4b7b.aspx

To achieve your goals, you might do something like that (you need your tag to be external to the union):

union MyUnionType { int data_int; double data_double; }

typedef enum { IntTag, DoubleTag } UnionTypeTag;

class MyVariableClass { private: MyUnionType m_variableField; UnionTypeTag m_variableFieldType; }

Another approach is to design your code so that at any point in the code path you know what "flavor" of union type you're handling.

My personal opinion is that the latter (always knowing what is your union "flavor") was in minds of K&R when they thought of the union concept.

Can you please initialze you pointer structExampleType<int>* structExamplePointer before using it.

As dereferencing an un-initialized pointer is what is causing the problem

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top