0

I am writing some code that inputs grid coordinates of "islands" (connected points on a grid) and finds the center of mass for each island. The code is successful for grids with a few large islands, however, it fails for grids with many small islands.

I've narrowed down the issue to rewind() failing on the 252nd loop-through. I have no idea why it fails as I've verified that island # 252 exists by printing the coordinates prior, and if I skip 252, the code fails on island 253, so I believe it is just rewind failing after 252 uses.

The code is quite large, so I'll try to just post the relevant parts:

FILE *f;

    if((f = fopen(argv[1], "r")) == NULL)
    {
            printf("Could not open file to read.\n");
            return 0;
    }
    while(!feof(f))
    {
            fscanf(f, "%d   %d      %d\n", &current_x, &current_y, &island_number);
            if(island_number > number_of_islands)
            {
            number_of_islands = island_number;
            }
    }
fclose(f);

This the first instance when f is used, but it's used again later, and again in the following for loop which is where the problem emerges:

for( int i = 0; i < number_of_islands; i++)
{
    printf("new loop: %d (number of islands: %d) \n", loop, number_of_islands);

 if(loop == 252)
 {
    printf("putting in x, y at 252...\n");
 }

This is where the code fails...

//putting numbers in x and y
    rewind(f = fopen(argv[1], "r"));

Here's a bit of the following part (probably not important):

if(loop == 252)
{
    printf("rewound at 252...\n");
    exit(0);
}


    while(!feof(f))
    {
            fscanf(f, "%d   %d      %d\n", &current_x, &current_y, &island_number);

            if(island_number == current_island_number)
            {
                    x_array[current_x] += 1;
                    y_array[current_y] += 1;

            }
    }

if(loop == 252)
{ 
    printf("finished putting in x, y at 252...\n");
    exit(0);
}

A sample of what the output looks like is this:

Everything looks good, except for the sudden segfault.

So my question is, why is rewind() suddenly segfaulting on the 252nd attempt?

  • 5
    Fyi, you might want to read this: [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). And I concur with @user3121023. You're probably running out of open file descriptors because you just abandon the last one with that hard-assignment from `fopen`, that is incorrectly assumed to always work. Assumption is the mother of all... – WhozCraig Jul 09 '16 at 19:58
  • On `feof` you might like to explore the ramifications of reading beyond the end of file, but better to just restructure the loops. In one case, you can use the return value from `fscanf` to control the loop. It's a *faux pas* not to test that function's value. Something like `while (fscanf(...) != 3) {...}`. – Weather Vane Jul 09 '16 at 20:00
  • 5
    Seems to be failing when you try to open a 256th stream (0..252 makes 253, plus stdin, stdout, and stderr makes 256)... assuming you're not closing the file between `fopen()`s (which you should be). – Dmitri Jul 09 '16 at 20:12
  • user3121023, WhozCraig, Dmitri: you're right! just needed to rewind f. Works like a charm now, thanks! Weather Vane, thanks for the tip, I'll keep that in mind. – continuing_zeroes Jul 09 '16 at 20:17
  • 1
    @continuing_zeroes glad it helped. What WeatherVane said isn't just something to keep in mind, it is a *bug* in your program, and from it your program invokes *undefined behavior*. You may not see it right now, but to be *correct*, you need to fix it. Best of luck. – WhozCraig Jul 09 '16 at 20:28
  • Oops mybad, I have the wrong test, which should be `while (fscanf(...) == 3) {...}` – Weather Vane Jul 09 '16 at 20:32
  • Please post a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). Make sure what is passed to `rewind()` is not `NULL`. – MikeCAT Jul 10 '16 at 00:12

1 Answers1

0

this: rewind(f = fopen(argv[1], "r")); does not rewind f. instead it assigns a new value for f, opening the same file and rewinding it (although it has just been opened). on some systems there is a limit to the open file descriptors you can have. why 252? i guess your limit is 256 and the kernel probably uses the remaining 4. to fix the problem you can either close the file first, or:

rewind(f);

this should work with no reassignment of f.

monkeyStix
  • 620
  • 5
  • 10