2016-09-22 4 views
0

면책 조항 : 이것은 숙제 과제의 일부이지만 전체 할당은 아닙니다.C - 세분화 오류로 연결되는 입력 문자열의 끝에서 함수가 종료되지 않습니다.

공백으로 구분 된 토큰을 검색하는 TKGetNextToken 호출 당 한 번이를 반환하고 반환 된 토큰에 대해 일련의 작업을 수행하는 "tokenizer"개체를 만드는 작업이 있습니다.

그래도 TKGetNextToken 기능이 작동하지 않습니다. 결과는 다음과 같습니다.

  1. 공백이 아닌 문자가 발견 될 때까지 입력 문자열을 통과합니다.
  2. 공백이나 NULL (문자열의 끝을 나타냄)이 발생할 때까지 입력 문자열을 계속 진행하면서 새 C 문자열에 문자를 추가하면됩니다.
  3. 공백이 있으면 c 문자열이 반환됩니다 문자열 내의 현재 위치는 TokenizerT 구조체 내에 저장됩니다.
  4. NULL이 발생하면 NULL이 TKGetNextToken에 대한 이후의 모든 호출이 NULL을 반환하도록 NULL이 TokenizerT 구조체에 저장되고 NULL이 반환됩니다.

그러나,이 함수는 문자열의 끝에서 중지하지 않고 대신은 바로 과거 불면과 프로그램이 충돌 할 때까지 메모리의 모든 내용을 출력합니다. 왜 이런 일이 일어나는지 알 수 없습니다.

여기 여기서 코드

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

struct TokenizerT_ { 
    char *currentToken; 
}; 

typedef struct TokenizerT_ TokenizerT; 


char *TKGetNextToken(TokenizerT *tk) { 
    char *cp = tk->currentToken; 

    while (cp != NULL && isspace(*cp)) { 
     cp++; 
    } 

    if (cp == NULL) { 
     tk->currentToken = NULL; 
     return NULL; 
    } 

    int size = 0; 
    char *token = malloc(sizeof(char)); 

    while (cp != NULL && !isspace(*cp)) { 
     size++; 
     token = realloc(token, size * sizeof(char)); 
     token[size - 1] = *cp; 
     cp++; 
    } 

    token = realloc(token, (size + 1) * sizeof(char)); 
    token[size] = NULL; 

    tk->currentToken = cp; 
    return token; 
} 

TokenizerT *TKCreate(char *ts) { 
    TokenizerT *tokenizer = malloc(sizeof(TokenizerT)); 
    tokenizer->currentToken = ts; 

    return tokenizer; 
} 

void TKDestroy(TokenizerT *tk) { 
    free(tk); 
} 

int main(int argc, char **argv) { 

    TokenizerT *tok = TKCreate(argv[1]); 
    char *token = TKGetNextToken(tok); 

    while (token) { 
     printf("\'%s\'\n", token); 
     token = TKGetNextToken(tok); 
    } 

    TKDestroy(tok); 
    return 0; 
} 

되는 명령 라인 인수 "100 200 300 400"주어진 샘플 출력이다. 그것은 입력 문자열 외부의 메모리에서 분명히 인쇄하고 있습니다. 당신이 개 while 루프에서

'100' 
'200' 
'300' 
'400' 
'' 
'╘jÉ' 
'╘hÉ' 
'' 
'' 
'' 
'' 
'' 

그리고 출력 GDB

Program received signal SIGSEGV, Segmentation fault. 
0x00401476 in TKGetNextToken (tk=0x701720) at test.c:28 
28   while (cp != NULL && !isspace(*cp)) { 
(gdb) backtrace 
#0 0x00401476 in TKGetNextToken (tk=0x701720) at test.c:28 
#1 0x0040151e in main (argc=2, argv=0x700cf0) at test.c:60 
+0

"함수는 문자열 끝에서 멈추지 않습니다"-> 문자열 끝을 테스트 할 코드가 없습니다. – chux

답변

2

에서이 조건은 null 문자에 대한 테스트를 포함해야한다. cp != NULL 테스트는 노 더-토큰 검사 점에서,

while (cp != NULL && *cp && !isspace(*cp)) 

나는 느낌을 얻을 : "문자열의 끝에 null 문자가 발생하지 않은"에 대한 적절한 시험은 따라서 사용 *cp입니다 어떤 경우에는 아마 while 루프에서 분해되어야합니다. 그것이 틀렸고 문자열 끝 테스트 인 경우 *cp 테스트로 대체해야합니다.

+0

주소가 NULL을 가리키는 지 확인하는 대신 널 문자를 확인해야 할 필요가 있습니다. 나는'cp == NULL 체크 '를'* cp =='\ 0 ''으로 대체 할 필요가 있었다. 단지'* cp' 체크가 나를 위해 작동하지 않았기 때문이다. 당신의 도움을 주셔서 감사합니다! – JRTN

관련 문제