1

My programme keeps producing a segmentation fault. I have simplified my code to the following:

#include <stdio.h>

void open_file(FILE** file)
{
        *file = fopen("test" , "wb");
        return;
}


int main ()
{
    int Tracks = 1;
    FILE* Files;
    int i = 1;

    Files = new FILE[Tracks + 1];

    printf("i = %d\n", i); //i = 1
    open_file(&Files + i);

    printf("i = %d\n", i); /i = 0
    fclose(*(&Files + i)); //Segmentation fault

    return 0;
}

I must be doing some really stupid pointer-error, but to me my pointer-arithmetics operations look fine... The problem is, that for some magic reason, the variable i changes its value to 0. Could someone explain to me why??

Thanks in advance!

Heinrich Heine
  • 303
  • 3
  • 12

2 Answers2

4

The problem is one of operator precedence, where the address-of operator have higher precedence than the addition operator. That means you are doing e.g. (&Files) + i, which is equivalent to (&Files)[i].

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • It is wrong either way. (&Files)[i] is wrong because only i=0 is valid. &Files[i] is wrong because it would cause a type mismatch. This answer is incorrect. The type of (&Files)[i] and type of &Files[i] are different. The problem is because the entire program is screwed up. Why in the world would open_file not just return FILE*... There is also no need to new FILE. fopen does that for you. – thang Feb 25 '15 at 14:06
  • It does (in an implicit way) answers why the variable i could be changed. – stefaanv Feb 25 '15 at 14:10
  • @stefaanv, it doesn't. The answer to why i could change is because (&Files)[1] points to the memory address occupied by i. I suspect the original poster knows that &Files + i is the same as (&Files)[i]. It's must be super implicit... – thang Feb 25 '15 at 14:12
2

fopen return a FILE*, so you may want to use an array of FILE* or a FILE** to store many of it.

Also you have to check the file to be opened before closing it.

#include <stdio.h>

void open_file(FILE** file)
{
    *file = fopen("test" , "wb");
    return;
}    

int main ()
{
    int Tracks = 1;
    FILE** Files = new FILE*[Tracks + 1];
    int i = 1;

    printf("i = %d\n", i); //i = 1
    open_file(&Files[i]);  // Will write at the address of the i-th element of Files.

    printf("i = %d\n", i); //i = 1

    // This have to be done for each element that correspond to an open file.
    // Add a for-loop should be considered.
    if (Files[i])          // Avoid segmentation fault
    {
        fclose(Files[i]);
        Files[i] = 0;      // So I know it is closed.
    }

    delete[] Files;
    return 0;
}

About the Files[i] = 0; you can take a look here.

About the magic i modification. Here what happens :

void open_file(FILE** file)
{
    // Write file address or 0 at the given address.
    *file = fopen("test" , "wb");
    return;
}    

int main ()
{
    int Tracks = 1;
    FILE* Files = new FILE[Tracks + 1];  // Files at address a
    int i = 1;                           // i probably at address a + sizeof(FILE*)

    printf("i = %d\n", i); // i = 1

    // here i = 1 so &Files + i = &Files + 1 = address of i.
    open_file(&Files + i); // Call to open_file with the address of i !

    // open_file failed and write 0 to the given address.
    printf("i = %d\n", i); // i = 0
}
Community
  • 1
  • 1
Orace
  • 7,822
  • 30
  • 45