K+R 2.4: bus error when assigning (Mac OS)

84 Views Asked by At

I'm currently trying to solve exercise 2.4 of the K+R book and came across an odd error I can't really reproduce elsewhere. I'm using:

Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin16.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

The code is:

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

/*
 * Write an alternate version of `squeeze(s1, s2)' that deletes each 
character
 * in s1 that matches any character in the string s2.
 */

void squeeze(char *s1, const char *s2);

int main(int argc, char **argv) {
  char *tests[] = {"hello", "world", "these", "are", "some", "tests"};
  for (unsigned int i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
    printf("'%s' = ", tests[i]);
    squeeze(tests[i], "aeiou");
    printf("'%s'\n", tests[i]);
  }
  return 0;
}

void squeeze(char *s1, const char *s2) {
  const size_t s2len = strlen(s2);
  s1[0] = s1[0];
  unsigned int j = 0;
  for (unsigned int i = 0; s1[i] != '\0'; i++) {
    unsigned int k;
    for (k = 0; k < s2len; k++)
      if (s1[i] == s2[k]) break;
    if (k == s2len)  // we checked every character once, didn't find a bad char
      s1[j++] = s1[i];
  }
  s1[j] = '\0';
}

GDB says:

Thread 2 received signal SIGBUS, Bus error.
0x0000000100000e57 in squeeze (s1=0x100000f78 "hello", s2=0x100000fa1 
"aeiou")
at exercise2-4.c:23
23    s1[0] = s1[0];

The error originally occurred at s1[j++] = s1[i], but I inserted s1[0] = s1[0] to test it independent of the variables and it occurred there as well. Obviously, I'm missing something here.

I'm compiling with clang -O0 -g -Weverything exercise2-4.c -o exercise2-4 if that's of any relevance.

Thank you very much for your time and sorry if this question's been answered before, I haven't found any question where the error occurs at such an odd place.

1

There are 1 best solutions below

1
On

You may not change a string literal. Any attempt to change a string literal results in undefined behavior.

From the C Standard (6.4.5 String literals)

7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.

Instead of the array of pointers to string literals

char *tests[] = {"hello", "world", "these", "are", "some", "tests"};

you should declare a two dimensional character array. For example

char tests[][6] = {"hello", "world", "these", "are", "some", "tests"};

Also you have to reserve enough space for each element of the array if you are going to append new characters to it.