Novice Pointers/Class Question

This is a discussion on Novice Pointers/Class Question within the C++ Programming forums, part of the General Programming Boards category; Hi there, Hopefully someone can answer this basic question. I'll post some sample code to help me explain: Code: **********Start ...

  1. #1
    Registered User
    Join Date
    Jun 2006
    Posts
    10

    Novice Pointers/Class Question

    Hi there,

    Hopefully someone can answer this basic question. I'll post some sample code to help me explain:

    Code:
    **********Start Run.cpp ***********
    #include "MyClass.h"
    
    using namespace std;
    
    int main(char args[])
    {
    	MyClass *mc = new MyClass[10];
    
    	delete [] mc;
    }
    **********End Run.cpp ***********
    
    **********Start MyClass.h ***********
    #ifndef MYCLASS_H
    #define MYCLASS_H
    
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    class MyClass
    {
    public:
    	string s;
            int i;
    	MyClass();
    };
    #endif
    **********End MyClass.h ***********
    
    **********Start MyClass.cpp ***********
    #include "MyClass.h"
    
    MyClass::MyClass()
    {
    	i = -1;
           s = "Hello";
    }
    
    MyClass::~MyClass()
    {
    	cout<<"Destructing MyClass"<<endl;
    }
    **********End MyClass.cpp ***********
    My question is, in the Run.cpp,

    MyClass *mc = new MyClass[10];

    will construct 10 instances of MyClass and have a pointer 'mc' point to the first one. We can then reference any via 'mc[0...9].

    Now as we are using the 'new' operator, this creates these 10 objects at runtime, presumably therefore placing them on the 'heap'. As I understand it (which I may be wrong), the stack grows from one end of the memory and the heap in the other, growing towards each other until they run out of room (I read this in an old book on compiler construction, so it may be wrong, please correct me if so).

    So... when I call

    delete [] mc;

    This deletes the pointer to these objects, but leaving the 10 objects on the heap ? This would be a memory leak ?
    Do these objects remain on the heap after the program has finished ? If so, how do I destroy them and free the memory ?

    I could call mc[0...9].~MyClass but this would simply call the destructor, but not actually freeing the memory as delete does ?

    For example, if this wasn't an array, and I had

    MyClass *mc = new MyClass();
    delete mc;

    Presumably this is actually freeing the memory ?

    I imagine that delete [] mc can't free memory of all the objects, as it doesn't know how many objects its pointing to (being a standard pointer only pointing to the first object?).

    Any general advice and information on this would be much appreciated.

    Cheers.

  2. #2
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Actually the pointer still exists after you delete it, but dereferencing it is undefined. The memory is free and the objects destroyed. They do not exist anymore, and you are done. delete also calls the deconstructors of the objects for you.

    I imagine that delete [] mc can't free memory of all the objects, as it doesn't know how many objects its pointing to (being a standard pointer only pointing to the first object?).
    Yes it can

  3. #3
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    Quote Originally Posted by C++Gamer
    I imagine that delete [] mc can't free memory of all the objects, as it doesn't know how many objects its pointing to (being a standard pointer only pointing to the first object?).
    As Tonto said, it can. How does it do this? Magic!

    Well not quite magic, but it's highly implementation dependant, so don't worry about it. (in case you're curious, common ways are adding a "sentinal" pointer at the end of the array or storing the size in the address just before the pointer, but YOU SHOULD NEVER RELY ON THESE!!)


    delete[] mc will call the destructor of each object and free the memory associated with each. mc itself will still have the address stored, which is now pointing to garbage.

    It's good to understand these concepts, but once you do, it's equally important to realise that in 99% of cases, you'd be better off using a standard library container of some sort (usually a vector)
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  4. #4
    Registered User
    Join Date
    Jun 2006
    Posts
    10
    Thanks for the information

    I'm using VS.NET 2003 IDE and I've a breakpoint inside the constructor as well as the destructor (as a cout<<"Con..." and cout<<"Des...").

    These couts are showing fine, but the Debugger refuses to goto the breakpoints for some reason. Even when I 'step' through the code, 'step into' seems to actually 'step over'.

    Strange I thought.

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,532
    the stack grows from one end of the memory and the heap in the other, growing towards each other until they run out of room
    No.

    The stack is a fixed size and is set by the operating system for each program. The heap is the current free memory on your computer. It is also known as Free-Store. So the heap size is, in practice, all your available memory minus all stack memory currently being used by running programs, minus all memory allocated by these programs.

    The heap tends to shrink when you use a program, and expand when you close it. So, it's the other way around.

    When you create an object with new, you are allocating memory from the heap, effectively denying access to those memory addresses needed by that object to other programs. When you free this object with delete, you are freeing these memory addresses (also known as, returning those addresses to the heap) effectively granting access back to those memory addresses to any program which may need them.

    delete [] mc;

    This deletes the pointer to these objects, but leaving the 10 objects on the heap ? This would be a memory leak ?
    Do these objects remain on the heap after the program has finished ? If so, how do I destroy them and free the memory ?
    No. The memory gets freed. No worries there. And it may even contain the same data. But it is now free to be used by any program. It's no longer allocated to your program. Do remember that "free memory" doesn't mean "empty memory". Free memory is any memory that is not allocated. Be it in some sort of "empty" state, or not.

    The pointer will still exist though, and on most machines still point to the memory address that contained the object it pointed to. However it is now undefined and trying to access it will give you undefined behavior.

    This pointer is called a dangling pointer. If your code tries to delete this pointer, you will get a compile-time error. To avoid this, is almost always a good idea to assign 0 to the pointer. That way the pointer will now point to nothing. Trying to delete it will do nothing.

    Code:
    MyClass *mc = new MyClass();
    delete mc;
    
    Presumably this is actually freeing the memory ?
    Yes.

    Code:
    I imagine that delete [] mc can't free memory of all the objects, as it doesn't know how many objects its pointing to (being a standard pointer only pointing to the first object?).
    Delete frees the memory associated with an object. An array, no matter how many elements it has, is one object.

    The [] operator between delete and the array name instructs the compiler that you are freeing a dynamically created array. In fact, depending on the compiler you may omit the [] and not get an error. Most possibly your compiler will not detect it. But you will get a run-time error.
    Last edited by Mario F.; 06-28-2006 at 05:19 PM.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Registered User
    Join Date
    Jun 2006
    Posts
    10
    Thanks very much, that explains alot.

    In fact, depending on the compiler you may omit the [] and not get an error. Most possibly your compiler will not detect it. But you will get a run-time error.
    Yea, I got that problem in VS.NET 03. As you probably know it doesn't give a compile time error, but will crash the program. The assertion failure (I think it was an assertion failure) didn't give me enough information to locate it quickly. Silly error. Is there any quick way to find out where such a problem lies ?

    A different example, I had a rather large program that was running fine, then I added a few declarations and that was all (to stringstream I think it was) and it started crashing (can't remember the specific error, it wasn't helpful and the screen that it brought up was an ASM screen. I had no idea why these declarations where crashing the program, but after a long long long line by line debug I found I was accessing an array 1 index outside it's declared bounds, fixing this fixed the problem. It is scary however that an error like this may not crash the program at the time, but may do so 2 weeks later and many lines of code later. I was wondering if there was any way of locating this as the source of the error quickly ? If you're wondering how I could write a reasonably large program but still not know such basic things, my uni teaches/taught java and I try to teach myself C++ in my spare time and would do some of my projects in it for practice even though I don't know many things.

    Finally, I presume the above code 'minus' the 'delete' line would result in a memory leak ? i.e. the allocated memory addresses not being freed back to the system before the program closes and therefore being 'allocated' until a reboot ?

    Thanks again.

  7. #7
    User
    Join Date
    Jan 2006
    Location
    Canada
    Posts
    498
    Is there any quick way to find out where such a problem lies ?
    I don't think there is a way, other than using your IDE debugger, or your internal debugger.


    Finally, I presume the above code 'minus' the 'delete' line would result in a memory leak ? i.e. the allocated memory addresses not being freed back to the system before the program closes and therefore being 'allocated' until a reboot ?
    Yes. If you do not run delete on a pointer to some memory, the end result is a memory leak. Regular variables are automatically deallocated when the variables go out of scope. The reason this is, is because pointers are really variables holding an address. So, the pointer is deallocated, but not the memory. That is why you need delete when deallocating pointers.

  8. #8
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,532
    Well, for starters, you should avoid arrays and use STL containers instead. For the most part, arrays should only be used on the internals of classes and probably only where performance needs to be fine-tuned. Containers offer a safe approach to arrays and offer also more functionality. There is really very few reasons to use arrays when one has access to the STL.

    But, if you insist on using raw arrays, there is no way you can protect yourself other than being careful with your code. This is the harsh truth. And even harsher is the knowledge that you are bound to make mistakes, no matter what.

    And yes, the above code without a delete will leak memory.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  9. #9
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    The reason this is, is because pointers are really variables holding an address. So, the pointer is deallocated, but not the memory. That is why you need delete when deallocating pointers.
    ...Which ties nicely with the idea of smart pointers, which can be regular variables whose destructors are called when they are going out of scope and they deallocate the memory they point to.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. another do while question
    By kbpsu in forum C++ Programming
    Replies: 3
    Last Post: 03-23-2009, 01:14 PM
  2. A novice programming question...
    By curious in forum C Programming
    Replies: 8
    Last Post: 11-12-2008, 06:09 PM
  3. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 10:47 PM
  4. Rtfm
    By XSquared in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 03-13-2003, 05:19 PM
  5. opengl DC question
    By SAMSAM in forum Game Programming
    Replies: 6
    Last Post: 02-26-2003, 09:22 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21