Thread: dynamic 2D array allocation

  1. #1
    Registered User
    Join Date
    Feb 2009
    Posts
    8

    Question dynamic 2D array allocation

    So I am revisting some of my old code and I was creating 2D array dynamically in 2 different ways:
    Code:
    double **allocate_array(int row_dim, int col_dim){
       double **result;
       int i;
       result=(double **)calloc(row_dim,sizeof(double *));
       result[0]=(double *)calloc(row_dim*col_dim,sizeof(double));
       for(i=1; i<row_dim; i++)
             result[i]=result[i-1]+col_dim;
       return result;
    }
    double **trainset;
    trainset=allocate_array(5,5);
    This way works fine but it appears I over dimensionalize it(I can access trainset[1][100]).
    And its really weird what is going on here, creating a pointer to an x*y array in the first array cell and then pointers to the start of each "row". I have no idea how C resolves a 2D call i.e. trainset[1][1].

    Also in the same program I used an inline method, that i tried putting into the allocate_array function instead of the first method:
    Code:
    double **allocate_array(int row_dim, int col_dim){
        double **result;
        int i;
        result = (double **) calloc(row_dim,sizeof(double));
        for(i=0;i<=row_dim;i++)
                    result[i]=(double *) calloc(col_dim,sizeof(double));
        return result;
    }
    double **trainset;
    trainset=allocate_array(5,5);
    But again the dimensions are off as I can access trainset[1][10000], and seg fault only at like trainset[1][1000000].

    Not sure if I should just ignore the over declaration and go with it, but its bugging me that I don't know what is going on. Its also strange that I can access trainset[5][1], which is the 6th and potentially non-existant, but its seg faults at trainset[6][1].

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Just because you don't (yet) segfault doesn't mean you own the memory, it just means you haven't walked off the end of the machine yet.

    Since trainset is a double**, trainset[1] corresponds to a double* (specifically, the second double* you allocated with that first calloc in your code). Then double[1][1] is the double just past the double pointed to by trainset[1][1] (trainset[1][0] would be the double pointed to).

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by deprekate View Post
    But again the dimensions are off as I can access trainset[1][10000], and seg fault only at like trainset[1][1000000].
    Both times, you're invoking undefined behaviour.

    One of the wonders of undefined behaviour is that anything is allowed to happen. That's what "undefined" is defined to mean in the C standard.

    One of the possibilities in "anything" is that two instances of undefined behaviour - such as you have - can produce differing results or behaviour. And one of those two can appear to be correct.

  4. #4
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    In both cases you are getting lucky that the program does not segfault when you go out-of-bounds. The behavior is inconsistent and definitely not reproducible.
    Quote Originally Posted by deprekate View Post
    So I am revisting some of my old code and I was creating 2D array dynamically in 2 different ways:
    Code:
    double **allocate_array(int row_dim, int col_dim){
       double **result;
       int i;
       result=(double **)calloc(row_dim,sizeof(double *));
       result[0]=(double *)calloc(row_dim*col_dim,sizeof(double));
       for(i=1; i<row_dim; i++)
             result[i]=result[i-1]+col_dim;
       return result;
    }
    double **trainset;
    trainset=allocate_array(5,5);
    This way works fine but it appears I over dimensionalize it(I can access trainset[1][100]).
    And its really weird what is going on here, creating a pointer to an x*y array in the first array cell and then pointers to the start of each "row". I have no idea how C resolves a 2D call i.e. trainset[1][1].
    The first calloc() sets aside memory for 5 pointers each of type double, casts the result to a double** pointer and points result at it. The second calloc() creates an array of 25 elements each of type double. It then sets each result[i] pointers to point to different locations of that array; for ex. result[0] points to the first element while result[1] points 5 elements beyond that.
    Quote Originally Posted by deprekate View Post
    Also in the same program I used an inline method, that i tried putting into the allocate_array function instead of the first method:
    Code:
    double **allocate_array(int row_dim, int col_dim){
        double **result;
        int i;
        result = (double **) calloc(row_dim,sizeof(double));
        for(i=0;i<=row_dim;i++)
                    result[i]=(double *) calloc(col_dim,sizeof(double));
        return result;
    }
    double **trainset;
    trainset=allocate_array(5,5);
    But again the dimensions are off as I can access trainset[1][10000], and seg fault only at like trainset[1][1000000].

    Not sure if I should just ignore the over declaration and go with it, but its bugging me that I don't know what is going on. Its also strange that I can access trainset[5][1], which is the 6th and potentially non-existant, but its seg faults at trainset[6][1].
    Again you are getting lucky, this doesn't mean it will happen all the time so don't count on it.

  5. #5
    Registered User
    Join Date
    Feb 2009
    Posts
    8
    Thanks for all the replies/help. So it appears I am allocating the correct way? but when I run something unexpected(line2[1][100000]) I am jsut getting a random event idiosyncracy?
    So basically keep it the way it is as long as I use only those dimensions I allocated?

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by deprekate View Post
    Thanks for all the replies/help. So it appears I am allocating the correct way? but when I run something unexpected(line2[1][100000]) I am jsut getting a random event idiosyncracy?
    So basically keep it the way it is as long as I use only those dimensions I allocated?
    What happens when you cross the road when you have a red light? It is not defined - you MAY have an accident with someone coming the other direction - but not every time. It is UNDEFINED - but you are certainly not guaranteed to get across without risk.

    The same applies to arrays and pointer dereference. The application will crash if you access memory that you should not access. But what is not defined is how far beyond what you allocated you can go - that will depend on the actual amount of memory allocated by the C library - it may decide to allocate a megabyte at a time in it's bottom layer, and than dole out the smaller portions as needed. It may also allocate exactly what you asked for, or rounded up to the next 4K, 64K or 2GB limit - it is up to the OS and C library to decide such things. If you allocate (say) 200MB, and then free it, the next allocation of 1 byte, you can go 199.99MB beyond that and still have a good amount of memory that is "accessible", because there is 200MB of accessible memory at that time.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. put matrix from file into 2d dynamic array
    By meriororen in forum C Programming
    Replies: 3
    Last Post: 06-08-2009, 07:51 AM
  2. from 2D array to 1D array
    By cfdprogrammer in forum C Programming
    Replies: 17
    Last Post: 03-24-2009, 10:33 AM
  3. Dynamic 2d Array
    By lvl99 in forum C Programming
    Replies: 8
    Last Post: 01-01-2009, 10:24 AM
  4. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM
  5. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM