2012-09-26 2 views
1
struct TokenizerT_ { 
    char* separators; 
    char* tks; 
    char* cur_pos; 
    char* next; 
    }; 

    typedef struct TokenizerT_ TokenizerT; 

    TokenizerT *TKCreate(char *separators, char *ts) 
    { 
    TokenizerT *tokenizer; 
    tokenizer = (TokenizerT*)malloc(sizeof(TokenizerT)); 

    //some manipulation here 

    tokenizer->tks = (char*) malloc (strlen(str)* sizeof(char)); 
    tokenizer->tks=str; 
    printf("size of tokenizer->tks is %zu\n", strlen(tokenizer->tks)); //this prints out the correct number (e.g. 7) 
    return tokenizer; 
    } 

    int main(int argc, char **argv) 
    { 
    TokenizerT *tk = TKCreate(argv[1], argv[2]); 
    printf("tk->tks: %zu\n", strlen(tk->tks)); //HOWEVER, this prints out the wrong number (e.g. 1) 
    } 

위 코드에서 알 수 있듯이 구조체에 대한 포인터로 작업하고 있습니다. 어떤 이유로 나는 tk-> tks에 대한 정확한 길이를 수신하지 못하고있다. TKCreate 함수에서 tks와 크기가 같아야하므로 이해할 수 없습니다. 누군가 설명해 주실 수 있습니까? 당신의 코드에 표시되지 않습니다 정의에있는 내가 str을 의심구조체를 가리키는 포인터

답변

2

는, TKCreate에 정의 된 지역 변수()입니다. 당신이 tokenizer- 할당하고 그렇다면> TKS는 TKCreate()의 범위 안에 적절한 문자열로하지만) (TKCreate 종료 (매개 변수와 지역 변수 포함) 스택의 내용이 해제됩니다에 점 STR의 값을 가질 수 있습니다 TKCreate()의 범위 밖에서 포인터를 참조하려고하면 모든 베팅이 해제되므로 닦아냅니다.

하나의 그럴듯한 수정 동적 tokenizer-> TKS의 스토리지를 할당하는 것입니다, 그래서 당신은() TKCreate을 종료 후에는 지속됩니다. 나는 당신이 malloc을 호출하는 것을 보았다.하지만 str의 명시적인 할당으로 그것을 덮어 쓴다. 대신 당신은을 통해 동적으로 할당 된 메모리에 STR (사용 strcpy와)의 내용을 복사해야합니다 : strcpy를 (tokenizer-> TKS, STR); 당신은 할당 연산자를 사용하는 경우, 메모리 누수를 만들고 이후에 파괴됩니다 지역 변수에 tokenizer->tks을 가리키는 malloc 당신을 준 포인터를 잃고 있기 때문에

+0

네 말이 맞아. 내가 어떻게 고칠 수 있니? – user1363410

+0

방금 ​​두 번째 단락을 추가하여 수정 사항을 설명했습니다. 도움이되는지 확인하십시오. –

0

당신은, tokenizer->tksstr의 내용을 strcpy한다 함수의 반환.

tokenizer->tks = (char *)malloc ((strlen(str) + 1) * sizeof(char)); 
strcpy(tokenizer->tks, str); 

또 다른 한가지 :

가 당신에게 무료 tk 자체 전에 free->tks하는 것을 잊지 마세요

그래서, 방법은 다음과 같이 될 것이다.

그래서, printf와 후 사용한다 : 구조와 다른 메모리 위치에서가 아니라 구조의 메모리 공간 안에 문자열을 (확보하지 아무런 문제가 없습니다

free(tk->tks); 
free(tk); 

, 그 이유를이다 프로그램을 실행 한 후 어쨌든 프로그램의 메모리가 지워지기 때문에 프로그램이 작 으면 그 둘을 해제해야합니다. 그러나 완벽하게 작동하고 큰 프로그램에서이 기능을 구현하려는 경우 메모리를 비우는 것이 좋습니다.

+0

'strlen (str) +1 '제발! –

+0

@JonathanLeffler 좋은 캐치! –

0

str이 정의 된 곳이 명확하지 않지만 함수의 로컬 변수 인 경우 문제가 범위를 벗어나므로 데이터를 덮어 쓰게됩니다.

당신이 할당 된 공간을 통해 str의 값을 복사 strcpy() 또는 memcpy() 또는 memmove()를 사용하는 잊어 버린 때문에 메모리를 유출하고, 당신은 포인터 str에 새로 할당 된 메모리에 대한 유일한 포인터를 덮어 씁니다. 복사 한 경우 문자열뿐만 아니라 후행 null에 충분한 공간을 할당하는 것을 잊었 기 때문에 범위를 벗어납니다. 할당이 성공했는지 확인해야합니다.

가짜 코드 :

tokenizer->tks = (char*) malloc (strlen(str)* sizeof(char)); 
tokenizer->tks = str; 

고정 코드 :

size_t len = strlen(str) + 1; 
tokenizer->tks = (char *)malloc(len); 
if (tokenizer->tks == 0) 
    ...error handling... 
memmove(tokenizer->tks, str, len); 

솜씨 (일부 그림과 타이밍 Why is Python faster than C 참조) strcpy()를 능가 할 수 memmove() 또는 memcpy() 사용. malloc()에 던지기를 사용하기 위하여 너 및 나를 excoriate 사람들; 나는 그들이 왜 그렇게 논쟁하는지 이해하지만, 나는 그들과 완전히 동의하지 않는다 (그리고 보통 나 자신을 사용한다). sizeof(char)은 정의상 1이므로, 그렇게 할 때 아무런 해가 없지만, 특별히 곱할 필요는 없습니다.

관련 문제