Thread: Dynamic Memory Allocation (Seg. Fault)

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    11

    Dynamic Memory Allocation (Seg. Fault)

    Hi everyone, first time user here. I just want to know if anyone can help me with a very simple piece of code.

    In a nutshell, I would like to dynamically allocate memory for a 2D array using new and delete. (I know I know, it is a common question but please keep reading). Instead of dynamically allocating the memory in the main() function, I would like to pass the 2D array to a function called "initArray(int *array[], int *numrows, int *numcols)". Once I initialize the array, I return back to the main () function and print a random value, say cout << array[1][1] << endl;. However, I received a segmentation fault which did not make any sense.

    Below is the entire code of my program:

    Code:
    #include <iostream>
    
    using namespace std;
    
    
    //Function Prototype
    void initArray (int *array[], int *numrows, int *numcols);
    
    //Main Function
    int main ()
    {
            int **a;
    
            int numrows = 5, numcols =5;
    
            //Pass the double pointer "a" along with the addresses of numrows and numcols
            initArray (a, &numrows, &numcols);
    
            //when returning from function initArray(), print out element at row 1, column 1
            cout << a[1][1] << endl;
    
            return (0);
    
    }
    
    void initArray (int *array[], int *numrows, int *numcols)
    {
    
            int i, j;
    
            array = new int* [*numrows];
    
            for (i = 0; i < *numrows; i++)
            {
                    array[i] = new int [*numcols];
            }
    
            for (i = 0; i < *numrows; i++)
            {
                    for (j = 0; j < *numcols; j++)
                            array[i][j] = i*j;
            }
    
            //print the element at row 1 and column 1
            cout << array[1][1] << endl;
    }
    For some strange reason, the cout statement in my initArray function prints normally whereas the same cout statement back in my main() function, it yells at me that I have a segmentation fault.

    If my logic is correct, I would assume that passing double pointer "a" essentially passes the address of where the double pointer is located in memory. My initArray function receives the address (int *array[] parameter), it should start initializing the matrix with the values i*j and writes it in memory. What I don't understand that why is the cout function does not cause a segmentation fault in the initArray function but occurs in my main() function.

    Would someone please give me a solution or an explanation to this?

    Thanks and with sincerest regards

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    array (within the scope of the initArray function) is a copy of the address/value passed in. Once you reassign this value in the first new call, the value stored locally within the initArray function is modified as desired however it does not affect the value stored in the calling function (the variable a in main). The solution to that is to pass the address of a into the function and have the function accept a pointer to a pointer to a pointer (or a reference to a pointer to a pointer).

    There is also no need to pass the row/column values by pointer, they are not being modified within the initArray function, only accessed.

    Now, I'm off to play Halo 3.
    Last edited by hk_mp5kpdw; 09-29-2007 at 08:23 PM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Sep 2007
    Posts
    11
    would you kindly please post the "fix" code on here? Some reason I tried doing your suggestion and it didn't work.

    Thanks and with sincerest regards

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I would suggest that instead of passing in an int*[], you change the return type to int*[] and return 'array', assigning it to 'a' in main.
    numrows and numcols should not be pointers. Did you fix that?

    Note that if this were proper C++ code, initArray would instead be the constructor of some class and there would be no need to pass an int*[] into or out of it.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    Registered User
    Join Date
    Sep 2007
    Posts
    11
    Quote Originally Posted by iMalc View Post
    I would suggest that instead of passing in an int*[], you change the return type to int*[] and return 'array', assigning it to 'a' in main.
    numrows and numcols should not be pointers. Did you fix that?

    Note that if this were proper C++ code, initArray would instead be the constructor of some class and there would be no need to pass an int*[] into or out of it.
    yup I fixed the numrows and numcols,

    Well I tried that method and some reason I'm still getting segmentation faults but this time it is in my initArray function.

    After the third iteration, it yells at me that I have a segmentation fault. Once again, am I missing something here?




    Code:
    #include <iostream>
    
    using namespace std;
    
    int** initArray (int *(**b), const int numrows, const int numcols);
    
    int main ()
    
    {
    
            int **c;
    
    
            c = initArray(&c, 5, 5);
    
            return (0);
    
    }
    
    int** initArray (int *(**array), const int numrows, const int numcols)
    {
            int i, j;
    
            *array = new int * [numrows];
    
            cout << "Hello Hello" << endl;
    
            for (i = 0; i < numrows; i++)
            {
                    *array[i] = new int [numcols];
                    cout << "Iteration " << i << endl;
            }
    
            for (i = 0; i < numrows; i++)
            {
                    for (j = 0; j < numcols; j++)
                            *array[i][j] = i*j;
            }
    
    
            return *array;
    
    }
    Last edited by dr_jaymahdi; 09-29-2007 at 10:27 PM.

  6. #6
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Using a reference:
    Code:
    #include <iostream>
    
    using namespace std;
    
    void initArray (int ** &array, const int numrows, const int numcols);
    
    int main ()
    {
        int **c;
    
        initArray(c, 5, 5);
    
        return 0;
    }
    
    void initArray (int ** &array, const int numrows, const int numcols)
    {
        int i, j;
    
        array = new int * [numrows];
    
        cout << "Hello Hello" << endl;
    
        for (i = 0; i < numrows; i++)
        {
            array[i] = new int [numcols];
            cout << "Iteration " << i << endl;
        }
    
        for (i = 0; i < numrows; i++)
        {
            for (j = 0; j < numcols; j++)
                array[i][j] = i*j;
        }
    
    }
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  7. #7
    Registered User
    Join Date
    Sep 2007
    Posts
    11
    Hi,

    Thanks for all the replies. I took up iMalc's advice, sample code below if anyone needs it:

    Code:
    #include <iostream>
    
    using namespace std;
    
    int** initArray (int **b, const int numrows, const int numcols);
    
    int main ()
    
    {
    
            int **c;
    
    
            c = initArray(c, 3 , 3 );
    
            int i, j = 0;
    
            for (int i = 0; i < 3; i++)
            {
                    for (int j = 0; j < 3; j++)
                            cout << c[i][j] << " " ;
    
                    cout << endl;
            }
    
            //cout << c[2][2] << endl;
    
            return (0);
    
    }
    
    int** initArray (int **array, const int numrows, const int numcols)
    {
            int i, j;
    
            array = new int * [numrows];
    
            cout << "Hello Hello" << endl;
    
            for (i = 0; i < numrows; i++)
            {
                    array[i] = new int [numcols];
                    cout << "Iteration " << i << endl;
            }
    
            for (i = 0; i < numrows; i++)
            {
                    for (j = 0; j < numcols; j++)
                    {
                            array[i][j] = i*j;
                            cout << "I'm over here" << endl;
                    }
            }
    
    
            return array;
    
    }
    To hk_mp5kpdw:

    Thanks for the solution , however I'm still not understanding the parameter in your modified function prototype as posted below:

    Code:
    void initArray (int ** &array, const int numrows, const int numcols)
    Does this mean that there will be a pointer to a pointer of the address of array? Because when passing in a double pointer "c" (lets just say), I would assume that int ** &array would receive the address where c is pointing at. What is really throwing me off is why would you need the address of array?

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The & in the function parameter indicates that it is a reference. That means that any changes to that double pointer will be reflected in the original double pointer in the calling function.

    BTW, is there a reason you're not using vector instead of a dynamic array?

  9. #9
    Registered User
    Join Date
    Sep 2007
    Posts
    11
    Quote Originally Posted by Daved View Post
    The & in the function parameter indicates that it is a reference. That means that any changes to that double pointer will be reflected in the original double pointer in the calling function.

    BTW, is there a reason you're not using vector instead of a dynamic array?
    Thanks for the explanation.

    As for your question, well I'm kinda developing a CAD tool which stores some variable amounts of nodes for each position in the array. Such that array[0] represents node 0, which will contain a pointer to a link list that contains the connected nodes that comes out of node 0.

    And plus, I'm doing this in C++ because I'm more familiar with it but it has been awhile since I programmed. I am kinda curious what's this vector talk is all about and how this can relate to what I'm doing.

    Thanks

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    I am kinda curious what's this vector talk is all about and how this can relate to what I'm doing.
    Well, it's like this: you say you're using C++, but you're really using C with a few C++ idiosyncrasies (specifically, new and cout, and now references). You use pointers for pass-by-ref (you didn't immediately recognize a reference), you use raw pointers, you manage your own memory, you're not writing object-oriented code, and you don't what vector is.

    Nothing wrong with writing C, but it's not C++.

    That said.

    vector is a class (template) in the C++ standard library. It is a dynamically resizable array that does the memory management for you. You could use a vector of vectors to achieve what you're doing currently, with much less hassle.

    Which doesn't solve the other problem, namely that allocating an array of pointers (or creating a vector of vectors) is a very inefficient way of creating true 2d arrays. What you really want is Boost.Multi_Array, which is an efficient multi-dimensional array that does the memory management for you and still allows you to choose things like memory layout (row-major or column-major).
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Registered User
    Join Date
    Sep 2007
    Posts
    11
    Quote Originally Posted by CornedBee View Post
    Well, it's like this: you say you're using C++, but you're really using C with a few C++ idiosyncrasies (specifically, new and cout, and now references). You use pointers for pass-by-ref (you didn't immediately recognize a reference), you use raw pointers, you manage your own memory, you're not writing object-oriented code, and you don't what vector is.

    Nothing wrong with writing C, but it's not C++.

    That said.

    vector is a class (template) in the C++ standard library. It is a dynamically resizable array that does the memory management for you. You could use a vector of vectors to achieve what you're doing currently, with much less hassle.

    Which doesn't solve the other problem, namely that allocating an array of pointers (or creating a vector of vectors) is a very inefficient way of creating true 2d arrays. What you really want is Boost.Multi_Array, which is an efficient multi-dimensional array that does the memory management for you and still allows you to choose things like memory layout (row-major or column-major).
    Wow, I didn't expect a lecture on how not to use a language.

    Well I intend on getting better in the C++ language and be able to take advantage of these available libraries that the language provides us. At any rate, thanks for your explanation on vectors. I think I will incorporate them in my future programming problems.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A question related to dynamic memory allocation
    By spiit231 in forum C Programming
    Replies: 2
    Last Post: 03-11-2008, 12:25 AM
  2. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  3. struct dynamic memory allocation
    By rotis23 in forum C Programming
    Replies: 2
    Last Post: 12-09-2002, 04:31 AM
  4. Dynamic Memory Allocation?
    By motocross95 in forum C++ Programming
    Replies: 11
    Last Post: 12-03-2002, 08:52 PM
  5. dynamic memory allocation - Please help
    By Space_Cowboy in forum C++ Programming
    Replies: 5
    Last Post: 11-13-2002, 05:20 PM