简体   繁体   中英

Segmentation fault on char string reference

I have a small C++ function which reverses a string in place:

void reverse1(string& s, int start, int end) {
  if (s.empty()) return;
  char tmp;

  while (start < end) {
    tmp = s[end];
    s[end] = s[start];
    s[start] = tmp;
    ++start;
    --end;
  }
}

This function works fine. However, when I rewrite it in c as below, I came across a segment fault on statement 11.

  5 void reverse2(char *s, int start, int end) {
  6   if (!s) return;
  7   char tmp;
  8   
  9   while (start < end) {
 10     tmp = s[end];
 11     *(s + end) = *(s + start);
 12     *(s + start) = tmp;
 13     ++start;
 14     --end;
 15   } 
 16 } 

Driver program that calls the function:

int main() {
  /* Flavor1 works */
  string a = "hello world2012!";
  reverse1(a, 0, a.length() - 1);

  /* Flavor2 does not - segmentation fault */ 
  char *b = "hello world2012!";
  reverse2(b, 0, strlen(b) - 1);
}

I use gcc v 4.6.1 to compile my program. When stepping through the code with gdb, the program crashes at runtime with segmentation fault.

The char string s is not a const. Can someone please suggest what's going on here? How do I fix this issue. Thanks.

Update: The reverse2 function is called on a string literal. The problem is I was trying to modify the string literal. As Jim and H2CO3 pointed out, this is an undefined behavior.

Now what's the exact difference between a string object (a) initialized with a string literal and a string literal (b)?

It depends on how you invoke your routine. If end is the length of the array, as is common in C, then s[end] is not a valid reference ... it's one character beyond s .

Also, !s is not equivalent to C++ s.empty ... it tests whether the pointer is NULL, rather than whether the string is empty -- for that, use !*s , !s[0] , s[0] == '\\0' , strlen(s) == 0 , etc.

The char string s is not a const.

It could fail anyway if it's a string literal constant; writing to such a string is Undefined Behavior.

you can rewrite the code as below

void reverse(char *s, int start, int end) {
  if (!s) return;
  char tmp;

  if( end >= strlen(s) )
      end = strlen(s)-1;

  while (start < end) {
    tmp = s[end];
    *(s + end) = *(s + start);
    *(s + start) = tmp;
    ++start;
    --end;
  } 
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM