2013-02-26 4 views
0

문자열의 일부 순서를 뒤집는 함수를 만들려고합니다. 포인터를 사용하는 것에 익숙하지 않고 문자열의 문자 위치를 액세스하여 부분 문자열을 복사 할 수 있지만 같은 위치에 다시 넣을 수는 없습니다 ...memcpy 중 세그먼트 오류

되돌려 진 부분 문자열을 원래 위치로 다시 복사합니다.

프로그램 수신 신호 SIGSEGV, 세그먼트 오류. 에서 0x00007ffff7b5dc66 ??() from /lib/x86_64-linux-gnu/libc.so.6

어떤 도움도 굉장 할 것입니다!

는 여기에 지금까지 가지고 무엇을 : 원래 문자열의 0 터미네이터가 포함되지 않는

void reverse(char* line, int start, int end){ 

     char str[end-start]; 

     memcpy (str , line + start , end-start); 

     reverseSubString (str); 

     memcpy (line + start, str , end-start); 

} 

void reverseSubString(char* str){ 

    int i, j, len; 
    char temp; 

    i=j=len=temp=0; 

    len=strlen(str); 

    for (i=0, j=len-1; i<=j; i++, j--) 
    { 
     temp=str[i]; 
     str[i]=str[j]; 
     str[j]=temp; 
    } 
} 
+0

은 왜 그냥 오히려 복사를 반전하고 복사하는 것보다, 장소에 문자열을 반전? strlen을 사용하는 대신에 reverseSubString에 길이 인수를 전달하십시오 (아래 답변에 언급 된 것처럼 버그의 출처입니다). –

+0

reverseSubString은 문제없이 실행되지만 어디에서 왔는지 알 수 있습니다. 나는 "솔리드"길이를 통합하기 위해 변경했지만 두 번째 memcpy는 여전히 세그멘테이션 오류를 발생시킵니다. 나는 원래 같은 문제를 겪고 있었다. – ThomDall

+0

"reverseSubString이 문제없이 실행됩니다."- 아니요, NUL 종료가 아닌 임의의 문자 시퀀스에서 발생하지는 않습니다. "원래는 같은 문제를 일으키고 있었지만 처음에는 되돌리려 고했습니다."- 무의미한 복사본을 추가하는 대신 이해하고 문제를 해결해야했습니다. –

답변

3
char str[end-start]; 

    memcpy (str , line + start , end-start); 

, 당신은 0이 종료되지 않은 char 배열을 가지고있다. 따라서

len=strlen(str); 

누가 그걸 알아 내지 못했는지 계산합니다. 그런 다음

for (i=0, j=len-1; i<=j; i++, j--) 
{ 
    temp=str[i]; 
    str[i]=str[j]; 
    str[j]=temp; 
} 

할당 된 메모리 외부에서 액세스합니다.

+0

reverseSubString은 문제없이 실행되지만 어디에서 왔는지 알 수 있습니다. 나는 "솔리드"길이를 통합하기 위해 변경했지만 두 번째 memcpy는 여전히 세그멘테이션 오류를 발생시킵니다. 나는 원래 같은 문제를 겪고 있었다. – ThomDall

+0

내 문자열이 수정 불가능한 메모리로 선언되었습니다. 쉬운 해결! – ThomDall

1

reverseSubstring()은 전달 된 문자열에서 strlen()을 호출하기 때문에 NUL 종료 C 문자열을 예상합니다. 그러나 reverse 함수에서 문자열을 NUL 종료하지 못합니다. 하나는 그렇게, 또는 더 나은하는 length 인수를 전달 :

void reverseSubString(char *str, size_t len) 
{ 
    int i, j; 
    char temp; 

    for (i = 0, j = len - 1; i <= j; i++, j--) { 
     temp = str[i]; 
     str[i] = str[j]; 
     str[j] = temp; 
    } 
} 

void reverse(char *line, int start, int end) 
{ 
    char str[end - start]; 
    memcpy(str, line + start, end - start); 
    reverseSubString(str, end - start); 
    memcpy (line + start, str, end - start); 
} 
+0

'reverseSubString (line + start, end-start)'는 같은 효과를 가지므로 ...'memcpy'와 VLA는 필요 없습니다. –

+0

@JimBalter 당연히, 그러나 나는 그것이 필요하다는 것을 말하지 않았다 - 다만 나는 과오를 고쳤다. 솔직하게 말해서, 나는 코드의 실행 시간에 대해서 생각조차하지 않았다. 이 코드는 작동하고 빨리 만드는 것은 내 의도가 아니 었습니다. (OP는 또한 빨리 만들려고하기 전에 작동하도록 걱정해야합니다). –

+0

요점은이 코드가 주석없이 단순히 포함하는 것보다 훨씬 복잡하고 오류가 발생하기 쉽고 비효율적이며 비효율적이라는 점입니다. "빨리 만들려고 노력하기 전에 작동시키기"에 관해서는 - 많은 불필요한 작업을하지 않을 때 코드 작업을하는 것이 훨씬 쉽습니다.문제에 대한 코드를 작성하는 것과 코드를 작성하는 것 사이에는 커다란 차이가 있습니다. 따라서 더 간단하고 효율적이며 코드를 "빨리"만들 수 있지만 문제 지향적이지는 않습니다. 나는 이전에 대해서만 이야기하고있었습니다. –