1. Not finding help here? Sign up for a free 30min tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Trouble Expanding an Array of pointers in C++

  1. May 3, 2007 #1
    1. The problem statement, all variables and given/known data

    I am working on a program that reads in names (strings), sorts them, and then later is searchable. The problem I am having is this. When I enter the first 20 elements of the array, everything works fine. When I enter the 21 element (when it goes into the if loop) I get an error that says:

    Debug Error!
    Program: ...

    HEAP CORRUPTION DETECTED: After Normal block (#118) at 0x00355930.

    CRT detected that the application wrote to memory after end of heap buffer.

    Abort Retry Ignore

    To make it easier to read, arrayExpansion is a const int defined in the header file as 10.
    CurrSize is defined at the beginning at 20.

    2. Relevant equations



    3. The attempt at a solution

    Code (Text):

    char    **  pNamesEntered;
        char    *   pNameToSearch;
        int         numEntered (0);
        int         index;
        int         CurrSize (20);
        int         compareResult;

        pNamesEntered = new char * [20];

        do  {
            cout << "Enter a name to be sorted and then searched: ";
            pNamesEntered [numEntered] = ReadString ();
            if (numEntered >= CurrSize)
                    {
                    CurrSize += arrayExpansion;
                    char ** pNew;
                    pNew = new char * [CurrSize];
                    for (index = 0; index < numEntered; index++)
                        pNew [index] = pNamesEntered [index];
                    //memcpy (pNew, pNamesEntered, numEntered * sizeof (char *));
                    for (int index = 0; index < numEntered; index++)
                        delete [] pNamesEntered [index];
                   
                    delete [] pNamesEntered;
               
                    pNamesEntered = pNew;
                    }
            } while (strlen (pNamesEntered [numEntered++]) > 0);
    The commented out memcpy line was my original attempt to copy the existing array to the new array. I get the same error when I use that line.

    The rest of my program works great, its this one particular section that I can't get.

    I suppose the question is, when you have dynamically created an array of pointers, and you have reached the limit of what you have created, how do you expand the array of pointers? I know how to make a single array bigger. This is my ReadString Function

    Code (Text):

    char * ReadString ()
        {
        char *      pChar;
        char        c;
        int         charCounter (0);
        int         CurrSize (arrayExpansion);

        pChar = new char [CurrSize + 1];
        while ((c = cin.get ()) != '\n')   
            {
            pChar [charCounter++] = c;
            if (charCounter >= CurrSize)
                    {
                    char *  pTemp;
                    CurrSize += arrayExpansion;
                    pTemp = new char [CurrSize + 1];
                    memcpy (pTemp, pChar, charCounter);
                    delete [] pChar;
                    pChar = pTemp;
                    }
                else;
            }
        pChar [charCounter] = '\0';
        return pChar;
        }

     
    Any help with understanding this would be outstanding. Thanks.
     
    Last edited: May 3, 2007
  2. jcsd
  3. May 3, 2007 #2
    two ways...
    [1] the first involves data structures, have you learned this before?
    [2] you want to go from "new char * [20];" new char * [20+k ];" for some k size (you can't actually do this in C/C++)...but what are you tring to achieve...

    (a) first think what is the difference between new char[n] and new char*[n];
    (b) next think of the statement you wrote

    "how do you expand the array of pointers? I know how to make a single array bigger." What exactly is it that you do to make a single array bigger?

    or call the first statement B, and the second one A...now treat B as statement A....

    That is you can say:
    i know how to make a single array bigger.
    I know how to make a array(pointer) of arrays bigger
    (....and then a new related question would be the next statement to follow that line of thinking)

    NOTE: the second method is only reasonable for small data sets like the problme you have....where you would need to copy the entire set.
     
  4. May 3, 2007 #3

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    Is there any particular reason you bothered to copy the pointers if you were just planning on deleting the memory to which the pointers are pointing?
     
  5. May 3, 2007 #4
    I thought what I was doing there was to create a new temporary array of pointers, copy the old array to the new array, delete the old array, then assign the new temp array info to a newly established pNamesEntered array.

    Honestly, I think a lot of my trouble is I am not quite grasping the array of pointers thing. Is that not a necessary step?

    Code (Text):

    if (charCounter >= CurrSize)
                    {
                    char *  pTemp;
                    CurrSize += arrayExpansion;
                    pTemp = new char [CurrSize + 1];
                    memcpy (pTemp, pChar, charCounter);
                    delete [] pChar;
                    pChar = pTemp;
                    }
     
    That is how I was able to expand a single array.

    But as I said, I can't wrap my head around how to do this same thing for the array of pointers. Will memcpy handle this type of function? I tried that, but I am not sure I used it correctly.
     
  6. May 3, 2007 #5

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    You did all of that. It's just that you also deleted everything that was being pointed to by the elements of the original array.

    The key piece of understanding that you're missing, I think, is that copying the pointer does not duplicate the memory to which the pointer points. It simply copies the pointer, so that you now have two pointers pointing to the same piece of memory.


    For a real world analogy -- you ran out of space in your address book. So, you buy a bigger address book and copy all of the addresses over from the old one into the new one, and destroy the old book. Would you want to destroy your friends' houses in this process?
     
    Last edited: May 3, 2007
  7. May 3, 2007 #6
    I would never do that. Unless they pissed me off.

    Seriously though, I went through and commented out the sections that were deleting the pNamesEntered elements.

    Now when I run the program, and enter the 21st element, it crashes and the Just in Time debugger (using Visual Studio 2005) says:

    An Unhandled Win32 exception error occurred in Program10.exe [1984]
     
  8. May 3, 2007 #7
    its because you can't you did not allocate for 21 pointers, you statically allocated for 20....do you know what data structures are?

    if not then you will need to allocate for that 21st...but you can't because you statically allocated for 20. Now you need to dynamically allocated the array of pointers.
    Now seeing your code you seem to know howt o allocate for an array of char now apply that to an array of pointers.
     
  9. May 3, 2007 #8
    I do know what a data structure is, but that is for next project. This project is supposed to be using pointers for everything.

    As far as dynamically allocating the array of pointers, that is what I thought I was doing with:

    Code (Text):
     CurrSize += arrayExpansion;
                    char ** pNew;
                    pNew = new char * [CurrSize];
                    for (index = 0; index < numEntered; index++)
                        pNew [index] = pNamesEntered [index];
                   
                   
                    pNamesEntered = pNew;

     
    pNew = new char * [CurrSize];

    That should be creating a new array of pointers. Then the for loop should be copying the pNamesEntered array to the pNew array.
    I thought that should be creating a new array with more space allocated.

    Am I on the right track here? Should I scrap it and start over?
     
  10. May 3, 2007 #9
    ah my bad it would help if i actually looked at the middle:
    ok here's the problem...you can't input the 21st right...

    now on pen and paper simulate how the logic of the code should work by
    removing everything in the if statement except { currSize+=...}.

    Jump straight to say the 19th iteration...and proceed from there.
    You should find your error by doing this...

    as for the middle portion of the code (the if statment ...it looks correct)

    Try to use less tabbing in an open forum like this...gets a little hard to read.
    CurrSize += arrayExpansion;
    char ** pNew;
    pNew = new char * [CurrSize];
    for (index = 0; index < numEntered; index++) pNew [index] = pNamesEntered [index];

    //and hurkyl was right you dont' need the 2nd portion
    //because from his analogy you keep the houses and destroy the
    //address in the book. Sort of like selling between people.

    delete [] pNamesEntered; //delete only the addressed

    pNamesEntered = pNew;
     
  11. May 4, 2007 #10
    Thanks for the help with this program. All of the different parts work now. I have one last issue with it. What is the code to delete the pNamesEntered array?

    I was trying:

    delete [] pNamesEntered;

    but that gives me an error.

    I tried:

    delete [] * pNamesEntered;

    on a whim...and the program works all around now..but does that free up the memory? That is the only thing I need to resolve in the program.
    My book has very limited information about the delete command.
     
  12. May 4, 2007 #11
    if u allocated teh array the syntax should be "delete [] arrayname;"
    copy and paste the error to the forum..and check if you have deleted it before hand...

    if you have a double pointer then you delete each element first...then delete the array of pointers.

    Funnything one of my HPC profs says ...ah in the end the computer does it for you so why bother...but its good practice to delete them on your own.
     
  13. May 4, 2007 #12

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    Because eventually, somebody (possibly you) is going to have the bright idea of taking the code you wrote and wrapping it up into a function call so that another program can call it a bunch of times.

    Which means that person is going to have to waste a lot of his time tracking down all of the stuff you didn't bother freeing.

    If, for some peculiar reason, it really does make a relevant1 performance difference, at the very least you should make a flag that controls whether or not cleanup code is executed.


    1: relevant being the key word: in almost every practical situation, you should first write the code correctly and simply. Optimization comes later in the software development process, and should not be done until you do actual performance analysis that suggests where optimization will make a relevant difference in runtimes.
     
  14. May 5, 2007 #13
    Code (Text):
    #include <iostream>
    #include <string.h>
    #include "Sort.h"

    using namespace std;

    void main ()
        {
        char    **  pNamesEntered;
        char    *   pNameToSearch;
        int         numEntered (0);
        int         index;
        int         CurrSize (20);
        int         compareResult;

        pNamesEntered = new char * [20];

        do  {
            cout << "Enter a name to be sorted and then searched: ";
            pNamesEntered [numEntered] = ReadString ();
            if (numEntered >= CurrSize)
                    {
                    CurrSize += arrayExpansion;
                    char ** pNew;
                    pNew = new char * [CurrSize];
                    for (index = 0; index < numEntered; index++)
                        pNew [index] = pNamesEntered [index];
                   
                    }
            } while (strlen (pNamesEntered [numEntered++]) > 0);


        // Printing names as they were entered
            cout << "You entered the following names: " << endl << endl;
            for (index = 0; index < numEntered; index++)
                cout << pNamesEntered [index] << endl;
            cout << endl;
           
           
        // Sorting and printing
            Sort (pNamesEntered, numEntered);
            cout << "Your sorted names are: " << endl << endl;
            for (index = 0; index < numEntered; index++)
                cout << pNamesEntered [index] << endl;
            cout << endl;

            do {
                cout << "Enter a name to search for: ";
                pNameToSearch = ReadString ();
                compareResult = Search (pNameToSearch, pNamesEntered, numEntered);
                if (compareResult == -1)
                    cout << "The name you entered is missing." << endl;
                    else
                        cout << "The name you entered is in number: " << compareResult << endl;
               
                } while (strlen (pNameToSearch) > 0);
           
            // Deleting the array
            for (int index = 0; index < numEntered; index++)
                delete [] pNamesEntered [index];
           
            delete [] pNamesEntered;
            pNamesEntered = 0;
        }
     
    That is the full code of the program, minus the headers and function files. If I run the program and use less than 21 elements, everything works fine. If I run the program and use 20+ elements, everything runs fine, it inputs as many names as I want, it sorts them, I can search them all successfully, but then when the program exits, I get the following error:

    Microsoft Visual C++ Debug Library

    Debug Error!

    Program: ...

    HEAP CORRUPTION DETECTED: after normal block (#118) at 0x00355928.
    CRT detected that the application wrote to memory after the end of the heap buffer.

    (Press Retry to debug the application)

    Abort Retry Ignore

    If I leave off the delete commands at the end, the for loop to delete the elements and the delete [] pNamesEntered; it exits properly, but again, I assume it doesn't free the memory.

    Any ideas?

    *edit
    I was messing with it some more, and I also get a Visual Studio Just-in-Time debugger error.

    An unhandled win32 exception error occurred in Program10.exe [12612]
     
    Last edited: May 5, 2007
  15. May 5, 2007 #14
    can u fix the indenting. TRy getting rid of all the stuff in the middle between the input adn the deletion. And see if it compiles...

    another thing you might want to do is dispaly the pointer address to track what pointer addys' your getting when you create each name string and see if they are the same when you are using them for sort and search.

    I'm still alittle confused at why your input code block works...
    because your currsize is 20, and you start your counter at 0...and when it hits 19 on teh end of the loop it increments to 20 which should crash on the next iteration when you read in idx 20.
     
    Last edited: May 5, 2007
  16. May 5, 2007 #15

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    This code is still your problem.

    I see you have:
    (1) Computed the size of the expanded array
    (2) Declared a temporary variable to point to the expanded array while it's being created
    (3) Allocated the expanded array
    (4) Pointed the temporary variable to the expanded array
    (5) Copied all of the values from your old array into the expanded array

    Forget anything?
     
  17. May 8, 2007 #16
    Deleting the temporary array?
    I am afraid I am at a loss at what to do at this point.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?



Similar Discussions: Trouble Expanding an Array of pointers in C++
  1. Array C++ (Replies: 2)

  2. C - array (Replies: 2)

Loading...