0

EXC_BAD_ACCESS occurred in *str++ = *end;. What's wrong with this?

#include <iostream>
using namespace std;
int main() {
    char *hello = "abcdefgh";
    char c = 'c';
    char *str = hello;
    //printf("%s",str);
    char * end = str;
    char tmp;
    if (str) {
        while (*end) {
            ++end;
        }
        --end;
        while (str < end) {
            tmp = *str;
            printf("hello:%s str:%c, end:%c\n", hello, *str, *end);
            *str++ = *end;
            *end-- = tmp;

        }
    }

    return 0;
}
Hiroaki Machida
  • 1,060
  • 2
  • 12
  • 23
  • 1
    [related post](http://stackoverflow.com/questions/1524356/c-deprecated-conversion-from-string-constant-to-char) about literals constness – Diego Apr 18 '15 at 22:06
  • What exactly are you trying to do? – Francisco Aguilera Apr 18 '15 at 22:07
  • 1
    Your answer is likely `*(str++) = *end;`, `(str+1) = *end; str++;` or `str++ = *end;`, but I confess my C++ skills are rusty and thus I can't guarantee nor explain myself on that answer. Your problem is that you're trying to access a value that is interpreted as constant by the runtime. Likely. – Felype Apr 18 '15 at 22:10
  • @francisco I'm trying to reverse chars! – Hiroaki Machida Apr 18 '15 at 22:21
  • I [get an error](http://coliru.stacked-crooked.com/a/644e3c3f21682a0a) with `-Wpedantic-errors`, and for good reason (this code is illegal as of C++11). The compiler just prevented me from changing constant data. – chris Apr 18 '15 at 22:52

2 Answers2

2

It is undefined behavior to attempt to alter a string literal. Change your code to the equivalent below, and you will see the issue:

const char *hello = "abcdefgh";
const char *str = hello;
const char * end = str;

So do you see why the line *str++ = *end; had a problem? You're attempting to write to a const area, and you can't do that.

If you want an even simpler example:

int main()
{
  char *str = "abc";
  str[0] = 'x';
}

Don't be surprised if this simple program produces a crash or segmentation fault when the

str[0] = 'x';

line is executed.

Unfortunately, string-literals did not have to be declared as const char* in C, and C++ brought this syntax over. So even though it looks like you are not using const, you are.

If you want the code to actually work, declare a writeable buffer, i.e. an array of char:

char hello[] = "abcdefgh";
char str[100];
strcpy(str, hello);
char end[100];
strcpy(end, str);
PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
1

It seems like you're trying to reverse the string. It also looks like you're overcomplicating things.

C-style strings declared on the stack have to be declared as const char *, which means you can't change the characters as they are constant.

In C++ we use strings, and string iterators:

#include <iostream>
#include <string>

using std::string;
using std::reverse;
using std::swap;
using std::cout;
using std::endl;

int main(int argc, const char * argv[])
{
    string hello("abcdefgh");
    reverse(hello.begin(), hello.end());
    cout << hello << endl;
    return 0;
}

Manually:

static void reverse(std::string & str)
{
    string::size_type b = 0, e = str.length() - 1, c = e / 2;
    while(b <= c)
    {
        swap(str[b++], str[e--]);
    }
}

Recursively:

static void reverse_helper(std::string & str,
                            string::size_type b,
                            string::size_type e)
{
    if(b >= e)
        return;
    swap(str[b], str[e]);
    reverse_helper(str, ++b, --e);
}

static void reverse(std::string & str)
{
    reverse_helper(str, 0, str.length() - 1);
}
Francisco Aguilera
  • 3,099
  • 6
  • 31
  • 57