0

I'm trying the squeeze program from K&R. However, I keep getting a bus error. The code below directly triggers the problem. Shouldn't this be portable?

int main() {
    char* str = "foo";
    for (int i = 0, j = 0; str[i]; ++i)
        str[j] = '.';
}

The function from the book:

void squeeze(char s[], int c)
{
    int i, j;

    for (i = j = 0; s[i] != '\0'; i++)
        if (s[i] != c)
            s[j++] = s[i];
    s[j] = '\0';
}
L.S. Roth
  • 447
  • 2
  • 14
  • What hardware are you using? – puppydrum64 Dec 13 '22 at 14:56
  • Probably a dupe of this: [**Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s\[\]"?**](https://stackoverflow.com/questions/164194/why-do-i-get-a-segmentation-fault-when-writing-to-a-char-s-initialized-with-a) – Andrew Henle Dec 13 '22 at 15:01

1 Answers1

0

str points to a string constant. Such constants are read only, so attempting to modify them triggers undefined behavior which in your particular case manifests in the program crashing.

Instead, declare str as an array, which can be modified:

char str[] = "foo";
dbush
  • 205,898
  • 23
  • 218
  • 273
  • I never understood this, it doesn't seem to be a limitation of the hardware but of C itself. Is there a reason why there's a difference? Does the compiler just turn this into `push 0x666F6F00` (or the equivalent in whatever assembly is being used?) – puppydrum64 Dec 13 '22 at 14:59
  • This worked! Does that mean that their function teaches undefined behaviour? – L.S. Roth Dec 13 '22 at 15:00
  • @puppydrum64 Compilers will typically place string literals in regions of memory marked read-only. – dbush Dec 13 '22 at 15:03
  • Do they have to, or is this a design choice? – puppydrum64 Dec 13 '22 at 15:07
  • @puppydrum64: Re “Is there a reason why there's a difference?”: The C standard specifies that a string literal causes the creation of an array of characters for which the behavior of attempting to modify them is not defined. The array has type “array of `char`” for historical reasons; if `const` had been in the language when string literals were specified, the array would be “array of `const char`”. In contrast, `char str[] = "foo";` creates an array for which the behavior of attempting to modify the elements is specified. – Eric Postpischil Dec 13 '22 at 15:07
  • @L.S.Roth The squeeze example from K&R didn't mention how the string was allocated on the caller side. It assumes read/write memory. – Lundin Dec 13 '22 at 15:09
  • @puppydrum64 On microcontroller systems, string literals are allocated in non-volatile, read-only flash memory. Which can't be written to. Which is a good thing since RAM is more valuable than flash and you don't want to download constants to RAM just for the heck of it. – Lundin Dec 13 '22 at 15:11