0

I am trying to implement floodfill. This works fine on a 500x500 matrix:

int ud[]={1,0,-1,0};
int lr[]={0,1,0,-1};

void fl(int x,int y)
{
   if(x<=0||x>n||y<=0||y>m)
   return;
   if(mat[x][y]) // seg fault occurs for this condition
   return;
   mat[x][y]=1;
   for(int i=0;i<4;i++)
   fl(x+ud[i],y+lr[i]);
}

But on a 600 X 600 matrix it's giving a segmentation fault. What could cause this?

HIBUDDY
  • 11
  • 2
  • What does the debugger say? – Dan Mašek Apr 08 '16 at 10:16
  • any more information as to where (source line) the runtime fault occurs? recursion depth? – Cee McSharpface Apr 08 '16 at 10:17
  • if n and/or m is 600, you should have a >= comparison operator. – Harry Apr 08 '16 at 10:19
  • N X M is the size of the grid. I'm using 1-based indexing so ( x > n || y > m) is correct. – HIBUDDY Apr 08 '16 at 10:20
  • Be sure to give a [Minimal, Complete, Verifiable Example](http://stackoverflow.com/help/mcve) when asking questions. Without a definition of `mat`, `n`, and `m` one can only *guess* what might be going wrong. Ideally, you should be able to reproduce your crash [in an online compiler](http://coliru.stacked-crooked.com/) so others can see it. – HostileFork says dont trust SE Apr 08 '16 at 10:23
  • 2
    Naive question : doesn't this algorithm bear the seeds of a stack overflow ? It does not seem to me that any honest TCO is possible here, and even if it was, do C++ compilers regularly implement it ? – Mathias Dolidon Apr 08 '16 at 10:25
  • 1
    @HIBUDDY You may be using 1-based indexing, but c++ doesn't (of course unless you forgot to mention you allocate the arrays bigger by 1). – Dan Mašek Apr 08 '16 at 10:26

2 Answers2

5

If you add some tracing into your code:

#include <stdio.h>
#include <iostream>

using namespace std;


int mat[1000][1000];
int n,m;
int ud[]={1,0,-1,0};
int lr[]={0,1,0,-1};

void fl(int x,int y, int depth)
{
  if(x<=0||x>n||y<=0||y>m||mat[x][y]) {
    return;
  }

  std::cout << x << ", " << y << " (" << depth << ")\n";

  mat[x][y]=1;

  for(int i=0;i<4;i++) {
    fl(x+ud[i],y+lr[i],depth+1);
  }
}

int main(int argc, char const *argv[])
{

   n=9,m=9;
   fl(1,1,0);

    return 0;
}

And observe the behaviour:

1, 1 (0)
2, 1 (1)
3, 1 (2)
4, 1 (3)
5, 1 (4)
6, 1 (5)
7, 1 (6)
8, 1 (7)
9, 1 (8)
9, 2 (9)
9, 3 (10)
9, 4 (11)
9, 5 (12)
9, 6 (13)
9, 7 (14)
9, 8 (15)
9, 9 (16)
8, 9 (17)
7, 9 (18)
6, 9 (19)
5, 9 (20)
4, 9 (21)
3, 9 (22)
2, 9 (23)
1, 9 (24)
1, 8 (25)
2, 8 (26)
3, 8 (27)
4, 8 (28)
5, 8 (29)
6, 8 (30)
7, 8 (31)
8, 8 (32)
8, 7 (33)
7, 7 (34)
6, 7 (35)
5, 7 (36)
4, 7 (37)
3, 7 (38)
2, 7 (39)
1, 7 (40)
1, 6 (41)
2, 6 (42)
3, 6 (43)
4, 6 (44)
5, 6 (45)
6, 6 (46)
7, 6 (47)
8, 6 (48)
8, 5 (49)
7, 5 (50)
6, 5 (51)
5, 5 (52)
4, 5 (53)
3, 5 (54)
2, 5 (55)
1, 5 (56)
1, 4 (57)
2, 4 (58)
3, 4 (59)
4, 4 (60)
5, 4 (61)
6, 4 (62)
7, 4 (63)
8, 4 (64)
8, 3 (65)
7, 3 (66)
6, 3 (67)
5, 3 (68)
4, 3 (69)
3, 3 (70)
2, 3 (71)
1, 3 (72)
1, 2 (73)
2, 2 (74)
3, 2 (75)
4, 2 (76)
5, 2 (77)
6, 2 (78)
7, 2 (79)
8, 2 (80) 

You will notice that it follows a snake-like pattern, while continuously getting deeper and deeper into recursion.

Traversal pattern

This was with 9x9 grid, imagine how deep it goes with 600x600.

What happens is you overflow the stack, and your program crashes.

Dan Mašek
  • 17,852
  • 6
  • 57
  • 85
3

If N and M is the size of the grid, you should have a >= comparison operator. Like so:

int ud[]={1,0,-1,0};
int lr[]={0,1,0,-1};

void fl(int x,int y)
{
  if(x<=0||x>=n||y<=0||y>=m||mat[x][y])
    return;
  mat[x][y]=1;
  for(int i=0;i<4;i++)
    fl(x+ud[i],y+lr[i]);
}
Harry
  • 1,362
  • 12
  • 19
  • 1
    Just beat me to it. What boggles me is how it managed to run with the 500x500 grid -- this should segfault every time. – Dan Mašek Apr 08 '16 at 10:24
  • and he is saying "I'm using 1-based indexing" so the array should have elements allocated at mat[m][n]... full code would be helpful – Cee McSharpface Apr 08 '16 at 10:26
  • 1
    @MathiasDolidon Yep, about 15000 calls deep: http://coliru.stacked-crooked.com/a/a913f459e5861b5c – Dan Mašek Apr 08 '16 at 10:33