1

I am trying to do a bubble sort on a c-string - see function below. The aim is to sort the characters according to the ASCII code.

The compiler does not complain until run-time at which point I get a segmentation fault. I have run gdb and the program runs fine until line 12. At line 12 the gdb debugger declares 'Process gdb-inferior killed'.

Why is line 12 incorrect? I have come across this issue elsewhere in my program - being unable to assign a character to an element of a c-string. I know that strcpy() is need for string assignment but with specific elements I thought it was ok. Any help MUCH appreciated.

    1. void bubblesort(char *str)
    2. {
    3.   int length = strlen(str);
    4.
    5.   for (int i = length - 1; i > 0; i--)
    6.     {
    7.       for (int j = 0; j < i; j++)
    8.         {
    9.           if (str[j] > str[j + 1])
    10.            {
    11.              char temp = str[j + 1];
    12.              str[j + 1] = str[j];
    13.              str[j] = temp;
    14.            }
    15.         }
    16.     }
    17.   return;
    18. }
ytoledano
  • 3,003
  • 2
  • 24
  • 39
  • How did you call `bubblesort`? – Yu Hao Dec 31 '15 at 13:18
  • @Yu Hao I am calling bubblesort like this: bool anagram(char *str1, char *str2) { // sort both arrays according to ASCII code bubblesort(str1); bubblesort(str2); // call compare on the two arrays if (compare(str1, str2)) return true; else return false; } – Christo Smallwood Dec 31 '15 at 15:29

2 Answers2

5

I've tested your code and it worked pretty well. I do have 2 theories on why your code snippet doesn't work.

Theory one: you're trying to write to a string literal which would require a line like this:

char* str = "abc";

There's a good chance your OS puts the "abc", you'd be referring to in a seperate read-only page, when you're writing to the variable at 12, this will cause a SEGFAULT.

More info here: Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?

Theory 2:

The mistake is likely in the strlen function which requires a null terminated string. For instance the Free BSD version looks like this:

size_t strlen(const char * str)
{
    const char *s;
    for (s = str; *s; ++s) {}
    return(s - str);
}

Imagine that you store "abc" in memory without null terminating byte. The strlen will look after the letter 'c', until it finds a single \0 (0x00) byte. This memory can be read only, in which case a SEGFAULT is created in line 12 when you attempt to write to it. (all previous access was read only)

Community
  • 1
  • 1
Work of Artiz
  • 1,085
  • 7
  • 16
0

I think I solved my own problem...

When calling a function like this:

foo("some string");

assuming the definition of the foo() of the form:

foo(char *str){.......}

will give a 'deprecated conversion' warning. This is annoying but can be ignored UNLESS you want to modify str in the function foo. The automatic conversion converts "some string" to a CONSTANT character pointer not a regular one. It does this whether you write foo(char *str) OR foo(const char *str) in the declaration/definition - it will just give a warning if you write the former.

In conclusion, it is better style to write foo(const char *str) in this case and if str must be modified within the function then a copy of the variable should be made within the foo function.