2015-01-26 4 views
0

왜 내가이 seg fault 오류가 계속 발생하는지 알 수 있습니까? "src"에서 "from"부분 문자열을 찾고 출력 문자열 "dest"의 "to"가있는 src의 "from"부분과 겹쳐지지 않은 부분을 모두 대체하는 프로그램을 실행하려고합니다. 또한 누군가이 케이스를 테스트 할 수있는 적절한 방법을 제공 할 수 있습니까? 내가 유형 (운동으로 이것을 시도) "무효"...이를 표시 할 수있는 방법을 너무 잘 모르겠어요으로Seg 오류가 발생 했습니까?

void find_replace(char* src, char* from, char* to, char* dest) 
{ 
    int count = 0; 
    int diff = strlen(to) - strlen(from); 
    int destlength = strlen(src); 
    dest = malloc(destlength); 
    for (int i = 0; i < strlen(src); i++) 
    { 
     int index = 0; 
     while (src[i+index] == from[index] && index < strlen(from)){ 
     index++; 
     } 
     if (index == strlen(from)) { 
     for (int j = 0; j < strlen(to); j++) { 
      dest[i+j+(count * diff)] = to[j]; 
     } 
     i += strlen(from) - 1; 
     count++; 
     } 
     else { 
     dest[i + (count * diff)] = src[i]; 
     } 
    } 
    return ; 
} 

는 테스트를 위해이 작업을 수행 할 수있을만큼 충분합니까?

int main (int argc, char *argv[]) 
{ 
    char* dest; 
    find_replace("hello my name is leeho lim", "leeho lim", "(insert name)" dest); 
    for (int i = 0; i < strlen(dest); i++) 
    { 
     printf("%c", dest[i]); 
    } 
    printf("\n"); 
} 
+3

문자열 리터럴은 C에서 수정할 수 없습니다. – ouah

+0

그래, 깨달았지만 그게 내 seg 오류의 원인이라고 생각하지 않습니다. –

+0

모든 경고가 용의자가 아닙니다. 제안 - 벽 – chux

답변

0

프로그램에 약간의 비틀기 만 있으면됩니다.

find_replace의 반환 값을 변경된 문자열에 대해 새로 할당 된 메모리로 변경하십시오. 대신

void find_replace(char* src, char* from, char* to, char* dest) 

를 사용하여 구현 약간

char* find_replace(char* src, char* from, char* to) 

변경합니다.

대신

dest = malloc(destlength); 

사용

char* dest = malloc(destlength); 

대신

return; 

사용

return dest; 

기능 사용 방식을 변경하십시오.

대신

char* dest; 
find_replace("hello my name is leeho lim", "leeho lim", "(insert name)", dest); 

사용

char* dest = find_replace("hello my name is leeho lim", "leeho lim", "(insert name)"); 

find_replace에 의해 반환 된 메모리 할당을 해제해야합니다. find_replace의 반환 형식이 void해야하는 경우 방법에 대한 옵션이 몇 가지있다

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

char* find_replace(char* src, char* from, char* to) 
{ 
    int count = 0; 
    int diff = strlen(to) - strlen(from); 
    int destlength = strlen(src); 
    char* dest = malloc(destlength); 
    for (int i = 0; i < strlen(src); i++) 
    { 
     int index = 0; 
     while (src[i+index] == from[index] && index < strlen(from)){ 
     index++; 
     } 
     if (index == strlen(from)) { 
     for (int j = 0; j < strlen(to); j++) { 
      dest[i+j+(count * diff)] = to[j]; 
     } 
     i += strlen(from) - 1; 
     count++; 
     } 
     else { 
     dest[i + (count * diff)] = src[i]; 
     } 
    } 
    return dest; 
} 

int main (int argc, char *argv[]) 
{ 
    char* dest = find_replace("hello my name is leeho lim", "leeho lim", "r sahu"); 
    for (int i = 0; i < strlen(dest); i++) 
    { 
     printf("%c", dest[i]); 
    } 
    free(dest); 
    printf("\n"); 
} 

업데이트, 영업 이익의 의견

님의 질문에 답변

free(dest); 

여기에 완벽하게 작동하는 프로그램입니다 dest에 필요한 메모리를 처리해야합니다.

  1. 호출 기능에 dest의 메모리를 할당하십시오.

    char* dest = malloc(SUFFICIENT_SIZE); 
    find_replace("hello my name is leeho lim", "leeho lim", "(insert name)", dest); 
    
    free(dest); 
    

    그런 다음, 라인 find_replace에서

    dest = malloc(...); 
    

    필요가 없다.

  2. dest의 메모리를 find_replace에 할당하십시오. 그런 다음 포인터에 포인터를 전달해야합니다.

    void find_replace(char* src, char* from, char* to, char** dest) 
    

    하고 대신 dest 기능에서의 *dest를 사용합니다.

    void find_replace(char* src, char* from, char* to, char** dest) 
    { 
        int count = 0; 
        int diff = strlen(to) - strlen(from); 
        int destlength = strlen(src); 
        *dest = malloc(destlength); 
        for (int i = 0; i < strlen(src); i++) 
        { 
         int index = 0; 
         while (src[i+index] == from[index] && index < strlen(from)){ 
         index++; 
         } 
         if (index == strlen(from)) { 
         for (int j = 0; j < strlen(to); j++) { 
          (*dest)[i+j+(count * diff)] = to[j]; 
         } 
         i += strlen(from) - 1; 
         count++; 
         } 
         else { 
         (*dest)[i + (count * diff)] = src[i]; 
         } 
        } 
        return; 
    } 
    

    find_replace으로 변경하십시오. 당신이 당신의 메인 프로그램의에서

    strlen(dest) 
    

    에 할당되지 않은 포인터를 액세스하려고하기 때문에

    char* dest; 
    find_replace("hello my name is leeho lim", "leeho lim", "(insert name)", &dest); 
    
+0

출력을 char *로 변경 하겠지만, 연습을 위해서는 선생님이 무효 출력으로 처리하길 원합니다. 하지만 고마워요! –

1

문제는 발생합니다.

이 이유는 포인터 dest 포인터의 값을 함수에 전달했기 때문입니다. 함수 내에 메모리를 할당했을 때 실제로 포인터에 저장된 메모리 주소를 수정하지 않았으므로 그것의 바깥 쪽 포인터.

포인터를 함수의 매개 변수로 보내면 실제로 포인터가 저장 한 메모리 주소를 보내는 것입니다. 포인터 자체가 아니라 포인터에 저장된 값을 보내는 것입니다.

문자열에 할당 된 메모리 주소를 얻으려면 함수가이를 반환하도록하거나 dest을 선언하고 pointer to a pointer으로 보낼 수 있습니다.

편집 : 다른 주석이 지적한대로 함수 내에서 수행하는 대신 main()에서 할당을 수행 할 수도 있습니다. 당신의 (원본) 코드를 사용하여 두 가지 문제가 있습니다

0

:

  1. 이 호출자에게 할당 대상 버퍼를 반환하여 find_replace() 기능을 제공하지 않으며,
  2. 이 안정적으로 충분히 할당하지 않습니다 목적지 버퍼를위한 공간.

원칙적으로 문제 (1)은 두 가지 방법으로 해결 될 수 있습니다. 공간은 호출자에 의해 할당 될 수 있고 함수에 전달 된 포인터가 함수에 의해 할당되거나 포인터가 호출자에게 반환 될 수 있습니다. 원래 코드는 함수에 공백을 할당하지만 은 호출자에게에 대한 포인터를 반환하지 않습니다.

호출자가 수행 할 것을 주장하는 것보다 입력 (2)를 만족시키기 위해서는 입력을 철저히 분석해야하기 때문에 함수가 할당을 수행하는 것이 바람직합니다.이 작업을 수행 할 때 수정 된 코드에서 무슨 생각해

char dest[4]; 
int canary = 0; 

find_replace("aaa", "a", "longer string", dest); 
assert(canary == 0); 

당신이 가능하게 당신이 어설 션 오류를 얻는다면, 아마도 당신이 얻을, 세그먼트 폴트를 얻을 가능성이 높습니다 - 누가 알 - 무엇을, find_replace()이없이 작업을 수행 할 수 없기 때문에 dest의 끝을 지나서 쓰고 그 결과는 정의되지 않습니다.

운동을 수행 할 때 함수에 반환 값 (예 : void)이 필요하지 않지만 사용자는 인수 목록을 통해 대상 문자열에 대한 포인터를 반환 할 수 있습니다. 해당 값 대신 포인터을 포인터로 전달하면 함수가 해당 값을 업데이트 할 수 있습니다. 서명은 다음과 같을 것입니다 : (. 함수가 문자열 리터럴을 수용하기위한 것입니다 경우, 적절한 경우에는 필요하지 않습니다 src, fromto에 대한 const qualifers를 참고)

void find_replace(const char *src, const char *from, const char *to, 
        char **dest_p); 

dest에 필요한 공간은 src의 길이와 더하기자를위한 것입니다. 이 from보다 길면 tofrom 문자열의 길이의 차이와의 모양의 수를 곱합니다.문자열. 그러나 그 길이에 대한 상한을 계산할 수 있고, 나중에 실제로 사용 된 공간의 양을 알게 된 후에 (필요한 경우) 할당을 축소 할 수 있습니다. 예를 들어이 결국, 숙제 때문에

void find_replace(const char *src, const char *from, const char *to, 
        char **dest_p) { 
    ssize_t src_size = strlen(src); 
    ssize_t from_size = strlen(from); 
    ssize_t to_size = strlen(to); 
    char *temp; 

    if (!from_size) { 
     /* special case: the 'from' string is empty ... */ 
     /* whatever you do, set temp to something valid or NULL */ 
    } else { 
     ssize_t size_diff = to_size - from_size; 

     if (size_diff < 0) size_diff = 0; 
     temp = malloc(1 + src_size + (src_size/from_size) * size_diff); 
     if (temp) { 
      /* use next to track the next unused position in temp */ 
      char *next = temp; 

      /* 
      * perform the substitution, updating 'next' appropriately as 
      * you go along (INSERT CODE AFTER THIS COMMENT) ... 
      */ 

      /* be sure to terminate: */ 
      *(next++) = '\0'; 

      /* shrink the string to the actual space used (optional): */ 
      next = realloc(temp, next - temp); 

      /* 
      * On (re)allocation error, next will be NULL and temp will still 
      * be a valid pointer. Otherwise, next will be a pointer to the 
      * space, not necessarily equal to temp, and temp might no longer 
      * be a valid pointer. 
      * 
      * An OK error recovery strategy is to just return a pointer 
      * to the full-size space. 
      */ 
      if (next) { 
       temp = next; 
      } 
     } /* else allocation failure; return NULL */ 
    } 

    /* 
    * The caller gets a pointer to the allocated space (if any). It is his 
    * responsibility to free it when it is no longer needed. 
    */ 
    *dest = temp; 
} 

실제 대체 코드는 연습으로 남아 있습니다.