1

I keep getting a segfault in some code I am trying and I am unsure why. Please take a look below (I've pulled the required into a single window, the functions are actually within 3 different files):

#define density 0.0005 

const int NBINS = 10;

double size;

typedef struct 
{
   int x_start;
   int x_end;
   int y_start;
   int y_end;
   particle_t* p;
   bool left;
   bool right;
   bool up;
   bool down;
} bins;

typedef struct 
{
  double x;
  double y;
  double vx;
  double vy;
  double ax;
  double ay;
} particle_t;

int find_option( int argc, char **argv, const char *option )
{
    for( int i = 1; i < argc; i++ )
        if( strcmp( argv[i], option ) == 0 )
            return i;
    return -1;
}

int read_int( int argc, char **argv, const char *option, int default_value )
{
    int iplace = find_option( argc, argv, option );
    if( iplace >= 0 && iplace < argc-1 )
        return atoi( argv[iplace+1] );
    return default_value;
}

void set_size( int n ) {
    size = sqrt( density * n );
}

void init_particles( int n, particle_t *p ) {
    srand48( time( NULL ) );

    int sx = (int)ceil(sqrt((double)n));
    int sy = (n+sx-1)/sx;

    int *shuffle = malloc( n * sizeof(int) );
    for( int i = 0; i < n; i++ )
        shuffle[i] = i;

    for( int i = 0; i < n; i++ ) 
    {
        int j = lrand48()%(n-i);
        int k = shuffle[j];
        shuffle[j] = shuffle[n-i-1];

        p[i].x = size*(1.+(k%sx))/(1+sx);
        p[i].y = size*(1.+(k/sx))/(1+sy);

        p[i].vx = drand48()*2-1;
        p[i].vy = drand48()*2-1;
    }
    free( shuffle );
}

void create_bins(int n, int num_bins, bins* b) {
   int x = 0;
   int y = 0;

   for (int i = 0; i < num_bins; i++) {
      b[i].x_start = x; 
      b[i].x_end = x + NBINS; 
      x += NBINS;

      b[i].y_start = y; 
      b[i].y_end = y + NBINS; 
      y += NBINS;

      b[i].p = malloc(n * sizeof(particle_t));
   }
}

void add_to_bin (int n, int num_bins, bins* b, particle_t* p) {
   for (int i = 0; i < n; i++)
       for (int j = 0; j < num_bins; i++)
          if (p[i].x >= b[j].x_start && p[i].x < b[j].x_end)    // Check if particle is within bin's x boundaries
             if(p[i].y >= b[j].y_start && p[i].y < b[j].y_end) {  // Check if particle is within bin's y boundaries
                b[j].p[0] = p[i];
             }
}

int main( int argc, char **argv )
{
   if( find_option( argc, argv, "-h" ) >= 0 )
   {
      printf( "Options:\n" );
      printf( "-h to see this help\n" );
      printf( "-n <int> to set the number of particles\n" );
      printf( "-o <filename> to specify the output file name\n" );
      printf( "-s <filename> to specify a summary file name\n" );
      printf( "-no turns off all correctness checks and particle output\n");
      return 0;
   }

   int n = read_int( argc, argv, "-n", 1000 );

   int num_bins = n / NBINS;

   bins* b = malloc (num_bins * sizeof(bins));

   create_bins(n,num_bins,b);

   particle_t *particles = malloc( n * sizeof(particle_t) );
   set_size( n );
   init_particles( n, particles );

   add_to_bin(n,num_bins,b,particles);

   return 0;
}

I can get most of these parameters setup except for the particle_t* p inside my bins struct. Below is how I am trying to accomplish that:

(I know setting p[0] over and over isn't going to accomplish what I want, I was just trying to dumb it down and have it set over and over)

gdb gives me the following result:

(gdb) run
Starting program: /workspace/particle/serial

Program received signal SIGSEGV, Segmentation fault.
0x0000000008001101 in add_to_bin (n=1000, num_bins=100, b=0x8415e70, p=<optimized out>) at bins.h:70
70                                      b[j].p[0] = p[i];

For some more background, the particles are being initialized in another function and I am trying to see which particles fall in a particular bin's area and add the particles that do to that bin, storing them in an array. I don't think I am grasping the idea of pushing the particles into an array correctly... I hope the above gives you a good idea of what I'm trying to do without being too much extra.

jrod091
  • 51
  • 7
  • 1
    [don't cast malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Barmar Mar 20 '19 at 23:53
  • 1
    The error suggests that `b[j].p` is not actually initialized. – Barmar Mar 20 '19 at 23:56
  • So the problem is probably in the code that creates the bins. – Barmar Mar 20 '19 at 23:57
  • Please provide all the relevant source code in one section. Dividing it up like you've done makes it more difficult to test it and help you with your problem. Please see https://stackoverflow.com/help/mcve. – brothir Mar 21 '19 at 00:04
  • I'm voting to close this question as off-topic because a MVCE should be provided but the fault is clearly in code not present. – Joshua Mar 21 '19 at 00:32
  • thanks for the comments @Barmar, I have edited the code provided to give a full perspective of my potential issue. Based on what you said, I would assume the last line in my `create_bins` function isn't actually creating the array? – jrod091 Mar 21 '19 at 00:39
  • The `particle_t` typedef needs to be before `bins`. – Barmar Mar 21 '19 at 00:46
  • 1
    It's a typo: `for (int j = 0; j < num_bins; i++)`. That should be `j++`. – Barmar Mar 21 '19 at 00:58
  • That caused the inner loop to be infinite and increment `i` forever, and `p[i]` eventually went out of bounds. – Barmar Mar 21 '19 at 01:01
  • I figured this out by printing `i` and `j` before `b[j].p[0] = p[i];` and I noticed that `i` was getting huge. – Barmar Mar 21 '19 at 01:02
  • of course it's something simple... thanks @Barmar! – jrod091 Mar 21 '19 at 01:03
  • 1
    In the debugger you could have looked at the values of `i` and `j`. – Barmar Mar 21 '19 at 01:04

0 Answers0