-1

I read a make_tempory_file demonstration in APUE, and confused about:

char good_template[] = "/tmp/dirXXXXXX"; /* right way */
char *bad_template = "/tmp/dirXXXXXX"; /* wrong way*/

void make_temp(char *template);

int main()
{
    char  good_template[] = "/tmp/dirXXXXXX"; /* right way */
    char  *bad_template = "/tmp/dirXXXXXX"; /* wrong way*/

    printf("trying to create first temp file...\n");
    make_temp(good_template);
    printf("trying to create second temp file...\n");
    make_temp(bad_template);
    exit(0);
}

void make_temp(char *template)
{
    int fd;
    struct stat sbuf;

    if ((fd = mkstemp(template)) < 0)

        err_sys("can’t create temp file");
    printf("temp name = %s\n", template);
    close(fd);
    if (stat(template, &sbuf) < 0)
    {
        if (errno == ENOENT)

            printf("file doesn’t exist\n");
        else
            err_sys("stat failed");
    }
    else
    {
        printf("file exists\n");
        unlink(template);
    }
}

The instruction explain it:

The difference in behavior comes from the way the two template strings are declared. For the first template, the name is allocated on the stack, because we use an array variable. For the second name, however, we use a pointer. In this case, only the memory for the pointer itself resides on the stack; the compiler arranges for the string to be stored in the read-only segment of the executable. When the mkstemp function tries to modify the string, a segmentation fault occurs.

I tried to understand the statement but stuck with stack

Does it refer to the stack where the arrow point to?

enter image description here

AbstProcDo
  • 19,953
  • 19
  • 81
  • 138

1 Answers1

3

When the mkstemp function tries to modify the string, a segmentation fault occurs.

The reason is because the string declared as char *bad_template = "/tmp/dirXXXXXX"; the bad_template is assigned to a character string literal.

In C, modifying a string literal is undefined behaviour

Reference - Section 6.4.5-6 of C99 Standard

A character string literal is a sequence of zero or more multibyte characters enclosed in double-quotes, as in "xyz". A wide string literal is the same, except prefixed by the letter L.

If the program attempts to modify such an array, the behavior is undefined.

Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
  • +1 for a correct answer that avoids discussing the stack at all. "Stack" is not a C language concept. Rather, it is a (very common) implementation detail. The important thing is that regardless of the nature or location of any object's storage, string literals must not be modified. Of course, any other array whose elements are non-`const`, such as the OP's `good_template`, may be modified. – John Bollinger Nov 14 '18 at 04:48
  • so I should forget stack, is it right to use stack here? @JohnBollinger – AbstProcDo Nov 14 '18 at 07:47
  • 2
    @A_Pivate - The reason you are getting a segmentation fault has nothing to do with the stack. You are modifying a string literal, which should not be modified. – Rishikesh Raje Nov 14 '18 at 08:27
  • @A_Pivate, I don't mean to say that there *isn't* a stack. I'm just saying that that's not a good way to think about the problem, nor really about *any* problem involving C language semantics. – John Bollinger Nov 14 '18 at 14:00