Wednesday, April 6, 2011

C : reverse a string in place. I used the prog answered in an earlier question. It compiles ok but crashes with segmenation fault

I call the function provided by Chris Conway (http://stackoverflow.com/questions/198199/how-do-you-reverse-a-string-in-place-in-c-or-c) from main (C code). When I run this program using cygwin, program crashes when it is in while loop (commented the lines where it breaks). Could you please explain what is going wrong here. Thanks

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

void strrev(char* z);

int main()
{
        char *a;
    printf("before reverse: %s\n", a);
        strrev(a); // function provided by Chris Conway
    printf("after reverse: %s\n", a);
    return 0;
}

void strrev(char *str) {
  char temp, *end_ptr;

  /* If str is NULL or empty, do nothing */
  if( str == NULL || !(*str) )
    return;

  end_ptr = str + strlen(str) - 1;

  /* Swap the chars */
  while( end_ptr > str ) {
    temp = *str;
    *str = *end_ptr;  //crashes here (cygwin gives segmentation fault)
    *end_ptr = temp;  //for testing, if I comment out line above, it crashes here
    str++;
    end_ptr--;
  }
}
From stackoverflow
  • The function is fine, but your main() does not appear to initialize the string a.

    Try:

    int main() {
      char a[1024];
      strcpy(a, "Some string");
      printf("before reverse: %s\n", a);
      strrev(a); // function provided by Chris Conway
      printf("after reverse: %s\n", a);
      return 0;
    }
    

    Note that I create a copy of "Some string" inside a (instead of directly assigning char* a = "Some String") because trying to alter a constant string directly will not compile. And if you did manage to compile (e.g. lax compiler, or you forced the constness away via cast/const_cast) then you run a very high risk of crashing your program, because "Some string" is actually in a portion of memory that is read-only on some systems, which is why a copy must be made inside a local variable (i.e. on the stack) or a new variable (allocated with new or malloc, i.e. on the heap.)

    strager : Or he can do: const char *a = "Some string";
    vladr : No, if he/she did that than strrev will attempt to modify a const, which should not compile. Moreover, since the const is actually coming from the executable image itself, even if the program were forced to compile, a crash may ensue (trying to alter memory mapped to the exec. image.)
    strager : Ah, my bad ... Forgot about that little detail. Silly me. Regardless, the compiler /should/ have warned him about using a non-const char * to store a string literal...
    Johannes Schaub - litb : well then, you can do char a[] = "Some string"; instead :)
    Johannes Schaub - litb : @strager, note that in C, unlike in C++, string literals are of type char[N] (not of type char const[N]), so the compiler could, but not must, warn. (well, for C++ neither, but there's more reason there, because of the const)
    ray : I feel like you just answered someone's homework question? :/

0 comments:

Post a Comment