CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8

Thread: CArray Question

  1. #1
    Guest

    CArray Question

    Hello All,

    I have encountered a problem in CArray which
    I don't know the reason ..


    // In my header file, i have a struct declaration
    // File.h
    typedef struct _tagStruct
    {
    int nCounter;
    CString strName;
    } REC_STRUCT;

    CArray < REC_STRUCT*, REC_STRUCT* > m_Array;

    // Then, in the implementation file
    // File.cpp

    void File::ArrayDemo()
    {
    m_Array.SetSize( 2 );
    REC_STRUCT * p = NULL;

    for ( int i=0; i<2; i++ )
    {
    p = new REC_STRUCT;
    p->nCounter = 100; // Assign Values
    p->strName = "HELLO";
    m_Array->SetAt( i,p );

    // Here, if I won't delete p, it will cause a
    // memory leak. But if I will delete p, refer
    // below :
    delete p;
    }

    // Here if p is deleted, data in the array is lost !!
    for ( int j=0; j<2; j++ )
    {
    REC_STRUCT * p1 = m_Array.GetAt( j );
    // p1->nCounter has now a NEGATIVE value
    // p1->strName is EQUAL to ""
    }
    }




    I would appreciate if somebody can tell the reason
    why CArray behaves like the one above!


    Thank you very much!




  2. #2
    Join Date
    Jul 1999
    Location
    Romania - Iasi
    Posts
    558

    Re: CArray Question

    Instead of:
    CArray < REC_STRUCT*, REC_STRUCT* > m_Array;


    why don't u use:
    CArray < REC_STRUCT, REC_STRUCT& > m_Array;


    ?

    Regards,
    Ovidiu

    fight to be the best of the rest because I am the best of the best -

  3. #3
    Join Date
    Jul 1999
    Location
    Germany, Dresden
    Posts
    71

    Re: CArray Question

    You have create a array of pointers with an known type.

    "p" is your placeholder for the memory address you get with "new REC_STRUCT".

    With "m_Array->SetAt( i,p )" you hold the ADDRESS of your structure, not the content.

    The CArray destructor only free's the space for the addresses (4 Byte) not your reference to the address.

    To avoid the memory leak use this:



    class CMyArray : public CArray < REC_STRUCT*, REC_STRUCT* >
    {
    public:
    ~CMyArray() { for (int nIdx = 0; nIdx < GetSize(); nIdx++) delete GetAt( nIdx ); }
    };




    Hint: if you call "ArrayDemo" more then once you must delete the old pointers (or reuse via "p = m_Array->GetAt( i )")





  4. #4
    Guest

    Re: CArray Question

    Hello Azur,

    Thanks for ur reply!:-) I really appreciate it !:-)
    However,with the code below,
    my question actually is "How to release the
    memory created by p = new REC_STRUCT;"

    I understand now that m_Array->SetAt( i,p )
    holds only the address of the structure.
    If I "delete p", m_Array don't have the
    contents now since the addresses it refers are
    released! But as I understand "delete p"
    is the only way to release the memory
    created by "p = new REC_STRUCT;" ..

    In conclusion, if I have to "delete p",
    information will be lost. If I don't,
    I'll end having memory leaks..

    Kindly tell me if my understanding is
    correct. Thank you very much!


    void File::ArrayDemo()
    {
    m_Array.SetSize( 2 );
    REC_STRUCT * p = NULL;

    for ( int i=0; i<2; i++ )
    {
    p = new REC_STRUCT;
    p->nCounter = 100; // Assign Values
    p->strName = "HELLO";
    m_Array->SetAt( i,p );
    }
    }






  5. #5
    Join Date
    May 1999
    Location
    Texas, USA
    Posts
    568

    Re: CArray Question

    Azur is right, but maybe didn't explain it to your content. The CArray only takes care of its own memory. If you allocate memory and assign that memory to the array, then you are responsible for releasing the memory. But you do not have to release it right when you add it to the array. Release it when you are through with it, like in the destructor as Azur suggested.


  6. #6
    Join Date
    Jul 1999
    Location
    Uitca, NY
    Posts
    120

    Re: CArray Question

    Here is my $0.00 worth. I don't understand why you choose to use a pointer to your structure instead of the structure itself. This simplifies life. Also if you create a pointer to your array and pass it to the function you can manipulate the array directly from the function. I had a similar situation in a program that I just wrote and handled it like this, your code base modified with my technique. I got the original technique from the book Mastering Visual C++ 4.0.

    // File.h
    typedef struct _tagStruct
    {
    int nCounter;
    CString strName;
    } REC_STRUCT;


    // Then, in the implementation file
    // File.cpp

    // Inside CFile class definition
    CArray < REC_STRUCT, REC_STRUCT > m_Array;
    // Create pointer to array to pass to function
    CArray < REC_STRUCT, REC_STRUCT >* m_pArray = &m_Array;

    ArrayDemo( m_pArray );

    void File::ArrayDemo( CArray < REC_STRUCT, REC_STRUCT >* pArray )
    {
    REC_STRUCT recMyStruct; // Declare a structure
    pArray->SetSize( 2 );

    for ( int i=0; i<2; i++ )
    {
    // Don't need new or delete, just reuse recMyStruct
    recMyStruct.nCounter = 100; // Assign Values
    recMyStruct.strName = "HELLO";
    pArray->SetAt( i, recMyStruct );
    // You can use the new and delete pair, just pointless.
    // recMyStruct will be destroyed when it goes out of scope
    }

    for ( int j=0; j<2; j++ )
    {
    REC_STRUCT * p1 = &recMyStruct; // Reuse the structure variable
    recMyStruct = m_Array.GetAt( j );
    // p1->nCounter has now a NEGATIVE value
    // p1->strName is EQUAL to ""
    // check p1 now.
    }
    // Also watch your subscripts as you go. m_Array has 2 elements,
    // indexes 0 and 1. I am not positive, but I think that you never reach
    // index 2 in you loops. This can also cause faulty data as the
    // program is reading uninitialized memory.
    }



    Pointers can cause confusion, especially when used with the new and
    delete operators. You can lose track of just what you are creating
    and deleting, the objects or the pointers.




  7. #7
    Guest

    Re: CArray Question

    Thanks to all your replies !:-))


  8. #8
    Join Date
    Jul 1999
    Location
    Germany, Dresden
    Posts
    71

    Re: CArray Question

    First I preferred the way suggested by Burlacu Ovidiu and Wayne Fuller.

    Second a answer how I understand your question about pointers.

    In the array you hold addresses or in other words simple 4 byte values. Your pointer "p" is also simple a placeholder for a 4 byte value.

    Excample:

    typedef struct tagXYZ
    {
    DWORD nValue;
    } XYZ, *PXYZ

    CArray <PXYZ,PXY> arr;

    // Address Content

    PXYZ p = NULL; // 0x00010000 0x00000000

    p = new XYZ; // 0x00010000 0x02000000

    p->nValue = 0x123; // 0x02000000 0x123

    arr.SetSize( 2 ); // 0x00300000 0x00000000
    // 0x00300004 0x00000000

    arr.SetAt( 0, p ); // 0x00300000 0x02000000

    // now you can "forgot" the pointer because you have saved the address in Element 0 at address 0x00300000

    // ...

    // later:

    PXYZ pOther = NULL; // 0x00015000 0x00000000

    pOther = arr.GetAt( 0 ); // 0x00015000 0x02000000

    // ... do somthing with "pOther"

    arr.GetAt( 0 );



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured