A string literal like "/bin/sh" is stored in .rodata, which is mapped read-only (see where things live in a C program). But its C type is plain char[N], not const char[N] (C++ fixed this, C kept it for historical reasons). So the compiler happily lets you do this:

char *p = "/bin/sh";   // compiles without a warning by default
p[0] = 'X';            // undefined behavior; in practice SIGSEGV
$ ./ub
Segmentation fault        (exit status 139 = 128 + SIGSEGV)

-Wwrite-strings: make the compiler tell you

-Wwrite-strings gives literals the type const char[N], so pointing a plain char * at one becomes a warning (an error with -Werror):

scratch.c:3:13: error: initialization discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
    3 |   char *s = "scratching surface";
      |             ^~~~~~~~~~~~~~~~~~~~

The fix is to say what you mean: const char *s = "...";. It’s not part of -Wall or -Wextra; you have to add it yourself.

Pointer to a literal vs. array initialized from one

char *s = "/bin/sh";   // A
char  s[] = "/bin/sh"; // B

They look almost identical but are very different:

  • A is a pointer. It points at the literal itself, in .rodata. With -Wwrite-strings this is the error above.
  • B is an array of 8 chars (7 + '\0'). The literal is only its initializer: the bytes are copied into the array. No pointer, no const dropped, and the array is yours to modify.
The variable sThe bytes "/bin/sh"s[0] = 'X'
A (local)8-byte pointer on the stackthe literal in .rodataUB / SIGSEGV
B (local)the array itself, on the stacka copy, inside the arrayfine
B (static or global)the array itself, in .dataa copy, inside the arrayfine

More differences:

  • A can be repointed (s = "other";). B can’t: arrays aren’t assignable, only their contents are.
  • sizeof s is the pointer size for A and the array size for B. For "/bin/sh" both happen to be 8 on a 64-bit machine; use a longer string to see them differ.

The real question isn’t “binary or stack”, it’s “am I pointing at the literal, or do I own a copy?”

References: the C23 standard, sections “String literals” and “Initialization”; man gcc (-Wwrite-strings).