Alejandro Alejandro - 4 months ago 23
C Question

Trying to overwrite a const char * is a bad access

I wrote a simple in-place string reversal function, which works on leetcode (interview practice), but gives a surprising bad-access error on my own system. It's such a simple function and everything else the debugger tells me seems like it should be A-OK. Why am I getting the bad access?

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

char* reverseString(char* s) {
char *t,*r,tmp;
t=r=s;
while(*(s++));
s-=2;
while(t<s){
tmp=*t;
*t=*s; //<--- this is where I have a bad access(?)
*s=tmp;
s--;
t++;
}
return r;
}

int main(){
char *s="12345";
reverseString(s);
return 0;
}


Bear with me, the debugger info is super simple.

╰─$ lldb ./a.out
lldb ./a.out
(lldb) target create "./a.out"
Current executable set to './a.out' (x86_64).
(lldb) r
r
Process 38750 launched: './a.out' (x86_64)
Process 38750 stopped
* thread #1: tid = 0xa0c378, 0x0000000100000f23 a.out`reverseString(s="5") + 99 at reverse-string.c:12, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x100000f91)
frame #0: 0x0000000100000f23 a.out`reverseString(s="5") + 99 at reverse-string.c:12
9 s-=2;
10 while(t<s){
11 tmp=*t;
-> 12 *t=*s;
13 *s=tmp;
14 s--;
15 t++;
(lldb) frame variable
frame variable
(char *) s = 0x0000000100000f95 "5"
(char *) t = 0x0000000100000f91 "12345"
(char *) r = 0x0000000100000f91 "12345"
(char) tmp = '1'
(lldb) call *s
call *s
(char) $0 = '5'
(lldb) call *t
call *t
(char) $1 = '1'
(lldb) call *t=*s
call *t=*s
(char) $2 = '5'
(lldb)


Notice that I can even call
*t=*s;
in lldb and get the expected result. What gives?

Answer

Modifying a string constant is undefined behavior IIRC. Even when you cast it to char * that doesn't make it okay.

Try making a non-const copy on the stack or heap first.