0

my overall program creates a new file based on a file name and mode that the user enters, then checks to see if the file exists. Following that it outputs whether file creation was successful. It should be simple, but when I compile and build (successfully) with Geany and run, I get the following error in the terminal window (but only after entering the mode "r+"):

./geany_run_script.sh: line 5:  7395 Segmentation fault      (core dumped) "./test" c


------------------
(program exited with code: 139)
Press return to continue

Then I ran it with gdb, after reading this

segmentation fault (core dump)

and got this error:

Program received signal SIGSEGV, Segmentation fault.
_IO_new_fclose (fp=0x0) at iofclose.c:54
54  iofclose.c: No such file or directory.

Here is my code:

#include <stdio.h>
#include <stdlib.h>

char filename[100];
char mode[2];

int main(int argc, char **argv)
{
    printf("Enter filename:\n>");
    scanf("%s", &*filename);
    printf("Select a mode from the list:\nr reading\nw writing\na append\nr+ reading &   writing (at beginning, overwriting)\nw+ reading & writing (overwrite on existing)\na+ reading & appending (new data appended at end of file)\n>");
    scanf("%s", &*mode);

    FILE * fp;
    fp = fopen(filename, mode);

    if (fp == NULL)
    {
        printf("Failed to open\n");
    }
    else
    {
        printf("Succesfully opened\n");
    }
    fclose(fp);

    return 0;
}

The gdb error comes up after I enter the filename, unlike with Geany where I get the error after I enter mode "r+".

Please help, and simply ask if you need additional data. Thanks in advance.

Edit: I updated the code, and the bit about when I get the error. For some reason, it is now at a different point in the program depending on whether I run it with gdb or with Geany.

Community
  • 1
  • 1
mee
  • 489
  • 5
  • 11
  • 19
  • Please post an [MCVE](http://stackoverflow.com/help/mcve). – R Sahu Jan 03 '15 at 03:12
  • Barring taking the address of a C++ iterator dereference (which this clearly isn't), `&*varname` makes literally no sense. Take *both* out. Just use `varname` for string to char-array extraction. And related, you really should be using `fgets` for this, or properly restricting your `scanf` format strings. – WhozCraig Jan 03 '15 at 03:28
  • ah yes i forgot to ask about that. Can you direct me to a resource explaining why this is please? The way I learned it, it is scanf("format_string", &variable); When I did it in this form though, my compiler gave me an error, and adding the * in between the & and the variable name fixed it. – mee Jan 03 '15 at 03:32
  • The expression value of an array is the address of its first element. I.e. `char var[n]` has `&var[0]` (or `var+0`, or just `var`, take your pick) as its first element. Any reasonable text on C will cover this in the section describing arrays and/or pointer arithmetic. – WhozCraig Jan 03 '15 at 03:34
  • alright, i've re edited my code and removed the &*'s. Geany still give me a seg fault error after I enter the mode, and gdb after I enter the file name – mee Jan 03 '15 at 03:37
  • Is your input `"r+"`, or just `r+`? The former will be a problem since `mode` doesn't have enough space for it. Not only that, it's the wrong thing to pass to `fopen`. – R Sahu Jan 03 '15 at 04:07
  • i type r+ without the double quotes – mee Jan 03 '15 at 04:24
  • Do *NOT* fix the code in your question when you get an answer, because then it's a useless question ("help me fix this code: ") – user253751 Jan 03 '15 at 05:11

1 Answers1

1

You'll need more than 2 characters for file modes: "r+" and the like (NUL terminator). Be careful to avoid buffer overflow.

   char mode[3];
   fgets(mode, sizeof(mode), stdin);

And the behaviour of fclose on a non-open file is undefined.

if (fp == NULL) {
    printf("Failed to open\n");
} else {
    printf("Succesfully opened\n");
    fclose(fp); /* only close if fp != NULL, and only close once */
}

all together:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(int argc, char **argv) {
    char filename[100];
    char mode[3];
    char *p;

    printf("Enter filename:\n>");
    fgets(filename, sizeof(filename), stdin);
    if ((p = strchr(filename, '\n')) != NULL) {
      *p = '\0'; /* remove any newline */
    }

    printf("Select a mode from the list:\n"
        "r reading\n"
        "w writing\n"
        "a append\n"
        "r+ reading & writing (at beginning, overwriting)\n"
        "w+ reading & writing (overwrite on existing)\n"
        "a+ reading & appending (new data appended at end of file)\n>");

    fgets(mode, sizeof(mode), stdin);
    if ((p = strchr(mode, '\n')) != NULL) {
      *p = '\0';
    }

    printf("opening %s with mode %s.\n", filename, mode);
    FILE *fp = fopen(filename, mode);

    if (fp == NULL) {
        printf("Failed to open\n");
    } else {
        printf("Succesfully opened\n");
        fclose(fp);
    }
    return 0;
}
ryanpattison
  • 6,151
  • 1
  • 21
  • 28
  • i changed my code to match yours but still no change in its behavior :/ – mee Jan 03 '15 at 03:53
  • @mee did you try `fgets` to avoid overflow? I suggest adding `printf("(%s, %s)\n", filename, mode);` before fopen to check that everything is good with the input first. – ryanpattison Jan 03 '15 at 04:07
  • by fgets do u mean i should substitute scanf for fgets? and yeah, i added the printf line you specified and it returns the correct values – mee Jan 03 '15 at 04:25
  • @mee yes, I've updated with an example. With your original code I could reproduce the segfault, but the changes fixed everything on my end. – ryanpattison Jan 03 '15 at 04:48