Thread: Particle mesh allocation fails for larger grid numbers

  1. #1
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665

    Particle mesh allocation fails for larger grid numbers

    Hello all, I'm currently studying how particle mesh simulations work and they seem to be a 3D allocation of grid points equally spaced from each other. I figure an easy way to allocate this memory is to use a 3D array and fill it with structs. If there's a better way then now is the time to tell me.

    If not, then yay for me and here's my code:

    Code:
    #include <stdlib.h> #include <stdio.h>   
     
    typedef struct node {
     
       int type;   
    
    
    } *node_ref;
    
    
    
    
    int main(int argc, char **argv) {
    
    
    
    
       int gl=128;
    
    
       node_ref omfg[gl][gl][gl];
    
    
       for (int i=0; i<gl; i++) {
          for (int j=0; j<gl; j++) {
             for (int k=0; k<gl; k++) {
    
    
                omfg[i][j][k] = malloc(sizeof (node_ref));
                omfg[i][j][k]->type = i;
             }
          }
       }
    
    
       for (int i=0; i<gl; i++) {
          for (int j=0; j<gl; j++) {
             for (int k=0; k<gl; k++) {
    
    
               free (omfg[i][j][k]);
             }
          }
       }
    
    
       return 0;
    
    
    }
    So as you can see, it's not that complicated. But the funny thing is, it works for smaller gl than 128 in the sense that gl=128 segmentation faults the code. Using gl=64 works fine though valgrind does give me some odd errors (Warning: client switching stacks? SP change: 0x7ff0005a0 --> 0x7fee00590to suppress, use: --max-stackframe=2097168 or greater)

    I don't actually know what that means but I have 8 GB of RAM and I doubt I'm eating up that much of it.

    So what's wrong here?

  2. #2
    Registered User
    Join Date
    Nov 2011
    Location
    Saratoga, California, USA
    Posts
    334
    Code:
    node_ref omfg[gl][gl][gl];
    What is 128^3? Static arrays are created on the stack.

  3. #3
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Quote Originally Posted by Tclausex View Post
    Code:
    node_ref omfg[gl][gl][gl];
    What is 128^3? Static arrays are created on the stack.
    So, 128^3 = 2,097,152 allocations of node structures. We give each structure 8 bytes so we wind up with 16,777,216 bytes total, not to mention the allocated memory given to the array itself, right? I think there's 32 bytes missing (something I noticed from valgrind output and my earlier calculations) so we should have 16,777,248 bytes total. So like 17 MB.

    I'm sorry, I'm rather ignorant in most cases as I'm not formally educated but I'm not sure why stack size is an issue. I've tried using "ulimit -s unlimited" and other numbers and they haven't done anything.

    I assume I should be able to write any structure that is allowed by my total RAM pool so if I wanted to, I could eat up like 6.5 GB (idle system is at 1.5 GB right now). But this stack size thing and heaps, what is this and why is it in my way?

  4. #4
    Registered User
    Join Date
    Nov 2011
    Location
    Saratoga, California, USA
    Posts
    334
    The "stack" is a relatively small memory allocation for storing local variables, passing parameters and return values and calling functions. According to your warning above, your stack is 2048K. Your total system memory is not available as a stack - thus you need to use dynamic memory allocation for such amounts of data, which will allocate space outside the stack. By itself, your omfg 3D array is as big as your stack, leaving no room for anything else.

  5. #5
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Okay, so I've got this now:

    Code:
    #include <stdlib.h> #include <stdio.h>   
     
    typedef struct node {
     
       int type;   
    
    
    } *node_ref;
    
    
    
    
    int main(int argc, char **argv) {
    
    
       int gl=128;
    
    
       node_ref ***omfg;
    
    
       omfg = (node_ref ***)malloc(gl*sizeof(node_ref**));
    
    
       for (int i=0; i<gl; i++) {
    
    
          omfg[i] = (node_ref **)malloc(gl*sizeof(node_ref*));
          for (int j=0; j<gl; j++) {
         
             omfg[i][j] = (node_ref *)malloc(gl*sizeof(node_ref));
          }
       }
    
    
       for (int i=0; i<gl; i++) {
          for (int j=0; j<gl; j++) {
     
             free (omfg[i][j]);
          }
          
          free (omfg[i]);
       }
    
    
       free (omfg);  
     
       return 0;
    
    
    }
    But if I try to change the type value, I segmentation fault. Is this a correct way to allocate memory?

  6. #6
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    You shouldn't cast the return value of malloc

    Also, check whether malloc was successful before using it.
    Fact - Beethoven wrote his first symphony in C

  7. #7
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Okay, so this should totally work and I must say, thank you guys for your help. I did want to kick and scream but I can only assume that it is a natural response.

    Either way, it allocates, doesn't fault and frees all the memory! Yay, I wrote good code for once!!! Now all the particle mesh physics belong to me!!!

    Code:
    #include <stdlib.h> #include <stdio.h>   
     
    typedef struct node {
     
       int type;   
    
    
    } *node_ref;
    
    
    
    
    int main(int argc, char **argv) {
    
    
       int gl=128;
    
    
       node_ref **omfg = malloc(gl*sizeof(node_ref **));
    
    
       for (int i=0; i<gl; i++) {
    
    
          omfg[i] = malloc(gl*sizeof(node_ref *));
          for (int j=0; j<gl; j++) {
         
             omfg[i][j] = malloc(gl*sizeof(node_ref));
             for (int k=0; k<gl; k++) {
    
    
                omfg[i][j][k].type = 0;
             }
          }
       }
    
    
       for (int i=0; i<gl; i++) {
          for (int j=0; j<gl; j++) {
     
             free (omfg[i][j]);
          }
    
    
          free (omfg[i]);
       }
    
    
       free (omfg);  
     
       return 0;
    }

  8. #8
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by MutantJohn View Post
    Yay, I wrote good code for once!!!
    I tend to disagree.

    You typedef a pointer which makes your code harder to read. I would suggest something like:
    Code:
    typedef struct node
    {
        int type;   
    } node_t;
    ...
    node_t ***omfg = malloc(gl * sizeof(*omfg));
    which makes it clear that "omfg" is a pointer to pointer to pointer to node_t. (Actually I don't see a reason for the typedef at all instead of just using "struct xxx" as the type.)

    Notice also how I use "omfg" with the sizeof operator. The basic idea is to always dereference the variable you are allocating memory for:
    Code:
    T *var_name; 
    var_name = malloc(sizeof(*var_name));
    Thus if you ever have to change the type of your pointer (T) you can do it at one single line.

    The same works for your other two malloc() calls:
    Code:
    omfg[i] = malloc(gl * sizeof(*omfg[i]));
    omfg[i][j] = malloc(gl * sizeof(*omfg[i][j]);
    Bye, Andreas

  9. #9
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    "The basic idea is to always dereference the variable you are allocating memory for:"

    Okay, I don't know what this means, actually.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Consider this example.

    int *p = malloc( 10 * sizeof(int) ); // make the coder do the work
    vs.
    int *p = malloc( 10 * sizeof(*p) ); // make the compiler do the work

    Which are both equivalent until there is a change of mind, and the code gets edited to
    double *p = malloc( 10 * sizeof(int) ); // oops, did you forget something?
    vs.
    double *p = malloc( 10 * sizeof(*p) ); // make the compiler do the work, automatically correct.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Numbers inside grid box help
    By hungrymouth in forum C Programming
    Replies: 1
    Last Post: 12-03-2012, 04:21 AM
  2. Replies: 7
    Last Post: 06-03-2010, 07:21 PM
  3. Searching through a grid of numbers
    By drag0n69 in forum C Programming
    Replies: 2
    Last Post: 03-18-2008, 12:52 PM
  4. Allowing larger numbers
    By DonW in forum C Programming
    Replies: 5
    Last Post: 09-18-2004, 02:02 PM
  5. Larger Numbers
    By Lynux-Penguin in forum C++ Programming
    Replies: 0
    Last Post: 01-03-2003, 02:44 AM