2016-08-05 2 views
-1

leetcode (인터뷰 연습)에서 작동하지만 내 시스템에서 놀랍게도 잘못된 액세스 오류가 발생하는 간단한 in-place 문자열 반전 기능을 작성했습니다. 그것은 아주 간단한 기능이며 디버거가 나에게 알리는 모든 것들은 그것이 A-OK 이어야만하는 것처럼 보입니다. 왜 나는 나쁜 접근을하고 있는가?const char * 덮어 쓰기 시도가 잘못되었습니다.

#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; 
} 

저와 함께 있으시면 디버거 정보가 매우 간단합니다. 심지어 lldb에 *t=*s;를 호출하고 예상 된 결과를 얻을 수 있습니다

╰─$ 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) 

알 수 있습니다. 뭐라 구요?

답변

3

문자열 상수를 수정하면 정의되지 않은 동작입니다. 당신이 그것을 잘 만들지 않는 char *에 던지더라도.

먼저 스택이나 힙에 비 const 복사본을 만들어보십시오.

+0

알 수 있습니다. 그래서 함수는 괜찮지 만 문자열 상수를 전달해서는 안됩니다. 이것이 테스트 케이스를 적절하게 만드는 leetcode가 오류를 던지지 않는 이유를 설명합니다. 이 일은 내가 할 수 없다면 걱정이되어서 ... – Alejandro

2

int main(){ 
    char *s="12345"; 

에서 s는 const char *이다. char * (경고를 표시해야 함)에 할당하지만, 지금은 변경할 수있는 것은 아닙니다. 여전히 const입니다. 오래된 OS에서는 보호되지 않으므로 데이터 저장소를 수정할 수 있습니다. 이것은 해커가 101 뭔가를 액세스 할 수 있습니다 - (아마도) const 문자열을 통해 기계 코드를 작성하고 나중에 실행, 그리고 빙고!

최신 버전 OS에서는 const 데이터를 메모리 페이지에 표시하여이를 보호합니다 (또한 Windows에서는 '데이터 실행 방지'로 표시되지 않습니다).

관련 문제