#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    13
    Rep Power
    0

    Unhappy Struggling with memory


    Hi,
    I am used to Java, so I'm struggling a bit with memory managment in C++ (Windows). What I would like to do is to ask some questions about the memory.

    1. I have managed to figure out this:

    Code:
    //Not on the heap
    const char * c = "Hello World!"
    
    //On the heap
    const char * c = new char[15];
    Is this correct?

    2. I can free memory allocated on the heap, but not any other memory. Like this:

    Code:
    //Not good
    char * c = "Hello World!";
    delete c;
    
    //Good
    char * c = new char[15];
    delete c;
    3. The final question: how can I tell (during runtime) whether or not a pointer points to the heap? Like this:

    Code:
    char * c = 0;
    if(something)
    {
       c = "Hello World!";
    } else
    {
       c = new char[15];
    }
    
    if(isPointerOnHeap(c))
    {
       delete c;
    }
    Is this possible?

    Thanks in advance,
    Nille
    Last edited by Nille; May 26th, 2003 at 09:35 AM.
  2. #2
  3. *bounce*
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2002
    Location
    Delft, The Netherlands
    Posts
    514
    Rep Power
    42
    First off, you're right on the first two questions. Now for the third :)

    I'm a C programmer rather than a C++ programmer, so I might be wrong here, but I don't think it's possible to distinguish between heap and text pointers (as in, pointing to somewhere in the text segment of the process).

    In cases like this I usually just copy the data from the constant to some newly allocated space:

    Code:
    char * s = "Hello world!";
    char * c = 0;
    
    if(something) {
       c = new char[strlen(s)+1];
       strcpy(c, s);
    } else {
       c = new char[15];
    }
    
    ... do some nifty stuff...
    
    delete c;
    Again, there might be a better way to do this in C++, but this is how I'd do it in C.
    "A poor programmer is he who blames his tools."
    http://analyser.oli.tudelft.nl/
  4. #3
  5. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    13
    Rep Power
    0
    I guess copying would be the most logical approach... but I would really like to be able to determine the location the pointer points to.

    I checked a VC++ book and looked at the layout of the memory. If I understand it correctly, all heap pointers point to a location in certain interval, and all non-heap pointer point outside of this interval. Is this a correct assumption? If so, shouldn't I just be able to check if the pointer is within this interval? Oh, and how can I find the interval? I am farely certain I can locate the size of the heap, but at which offset does it start?

    A lot of questions, I know. To sum up:

    1. How can I find the offset of the heap?
    2. How can I find the size of the heap?
    3. If (pointer >= offset && pointer < offset + length) can I assume it is on the heap?

    Thanks for you answer,
    Nille
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    Pointers are one of the big differences between Java and C++. I went from C/C++ to Java, so I never had to go through that.

    First, on your original question #2, you are essentially correct, but when you are deleting an array, you need to use the array delete:
    Code:
    char * c = new char[15];
    delete [] c;
    Otherwise, as I understand, the entire array would not be freed up and you'd have a memory leak.

    As for trying to map out the heap, there are low-level ways of doing it; try looking for a program called HeapWalk and see if you can get the source code for it.

    I don't know whether the new standard defines how the heap is to be maintained, but I don't think that it does. So what you figure out on one system with one compiler might not work with another.

    Now, as for copying pointers. There is a big difference between copying a string and pointing to a string, as you appear to be aware. This difference can cause some unexpected problems.

    It's easier to describe with code:
    Code:
    char * s = "Hello World!";  // points to a string in non-heap memory
    char * c2 = NULL;  // doesn't point to anything
    char * c3 = NULL;  // doesn't point to anything
    
    void foo(void)
    {
        char *c;
    
        if(something)
        {
            c = new char[strlen(s)+1];  // points to a block in heap
            strcpy(c,s);
        } 
    
        c2 = c;  // points to the same location as c does
        c3 = new char[strlen(c)+1];  // points to a block in heap
        strcpy(c3,c);
    
        delete [] c; 
    }
    
    void foobar(void)
    {
        cout << c2 << endl;  // ERROR!  c2 no longer points to valid data!
        cout << c3 << endl;  // Works!  c3 kept its own copy of the string, 
                                    // and so is unaffected by c having gone away.
    }
    If you assign a pointer to a pointer, all you are doing is setting them to point to the exact same location in memory. If one of the pointers deletes that location, then all the other pointers pointing to the same location will all be invalid.

    The lesson here is that in C and in C++ all variables declared within a code block automatically cease to exist when you exit that code block. A code block is defined as a collection of statements placed between braces, like the body of a function. If you want to make a value declared with a code block to be available after exiting that code block, then you need to copy it to a variable outside the code block.


    I'm not sure what you are trying to do with your isPointerOnHeap function. If you just want to ensure that you don't delete a non-heap pointer, then there is a far easier and better way. If you new something, it is being created on the heap. So all you need to do is to delete everything that you new and only that. One piece of advice I recently read is that as soon as you write the new statement, also write its delete statement so you don't forget. My particular practice is, upon creating a class, I immediately write the default constructor with the default initializations and the destructor with the deletes for the dynamically allocated properties. Then when I add a new property to the class, I immediately add it to the destructor if applicable and then I add it to the constructors.

    However, if you really do want to play with the heap, then there should/could by compiler-specific constants and functions available. MS Visual C++ has such; just look in the help file under "heap constants".
  8. #5
  9. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    13
    Rep Power
    0
    Thanks for your generous response!

    There's actually a function called HeapWalk. But all it does is enumerates memory blocks allocated with HeapAlloc. There has got to be some way to receive the offset and size of the heap, since memory can be allocated there in the first place.

    I understand pointers in most contexts. The memory layout and allocation of memory can get me confused sometimes though. It's a u-turn from java, I'll tell you that! But, there's one thing about pointers (and references) I would like to ask. In this case:

    Code:
    void myFunction()
    {
       String myString = getString();
    }
    
    String& getString(const char * str)
    {
       return *(new String(str));
    }
    Will the allocated string get destructed when 'myString' runs out of scope?

    As for checking whether or not a pointer points to the heap; I've made a String class and a StringBuffer class (java mimic) that should be as light as possible and as easy to handle as possible. So when I pass a String (by copy) to a function, the copied string should point to the same buffer as the original string. When no strings reference the buffer, the buffer should be deleted.

    The problem is that I don't know how the memory has been allocated. Hence the 'isOnHeap' function - if the buffer is on the heap it must be deleted. If it is not, it shouldn't be deleted. I found a function called _CrtIsValidHeapPointer, but that's for debugging only (ie I can't compile when I use it).

    Code:
    //Case one
    char * doNotDelete = "Hello World";
    String str = doNotDelete;
    
    //Case two
    char * doDelete = new char[15];
    String str = doDelete;
    So when the string is being destructed, I don't know what to do. I have currently solved it by copying the char pointer (doNotDelete and doDelete) onto the heap whether or not it is needed. The optimal case, however, would be to allocate and deallocate as little memory as possible.

    Unfortunatly, neither the heap constants nor the heapwalk can be used. They are all used to check that status of memory allocated.

    I am about to give up...

    Thanks for responding, though...

    Nille
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2000
    Posts
    114
    Rep Power
    15
    You could try overloading the new operator for your class (and if you're really desperate, you could overload the global operator) to implement some sort of referencing counting ( you could even store the pointer in static (global) memory to keep track of which pointers were new'd. Also, you could look at:

    http://www.mindview.net/Books/TICPP/...ngInCPP2e.html
    excellent online C/C++ books.

    http://www.hpl.hp.com/personal/Hans_Boehm/gc/
    for a garbage collecting library.

    http://www.boost.org/libs/smart_ptr/
    for a class to help you manage memory.

IMN logo majestic logo threadwatch logo seochat tools logo