2012-12-01 4 views
0

저는 C-String 연결을해야하는 상황에 처해 있습니다. 그래서 배우기 위해 자기 자신을 따라하기로했습니다. (이것은 개인 프로젝트이므로 모든 세상의 시간, 정말로).C 문자열 연결 문제 함수

지금까지 나는이 두 가지 기능 (설명 아래)을 마련했습니다

static inline // make inline to leave out the stack manipulation 
size_t StrLength(const char* string) 
{ 
    return strnlen(string, strlen(string)); 
} 

static void concatstr(char** dest, const char** src) 
{ 
    const size_t destlen = StrLength(*dest); 
    const size_t srclen = StrLength(*src); 

    const size_t total_len = destlen + srclen; 

    const size_t totalLenNull = total_len + 1; 

    char* tmp = (char*)malloc(sizeof(char) * totalLenNull); //<-- Because of this... 

    size_t counter = 0; 

    for(size_t iDest = 0; iDest < destlen; ++iDest) 
     tmp[ counter++ ] = *dest[ iDest ]; 

    for (size_t iSrc = 0; iSrc < srclen; ++iSrc) 
     tmp[ counter++ ] = *src[ iSrc ]; 

    *dest = (char*) realloc(*dest, totalLenNull); 

    strncpy(*dest, tmp, total_len); 

    free(tmp); 

    tmp = NULL; 
} 
인라인 StrLength 기능 뒤에 아이디어는 내가 제대로 인라인 이해의 경우는 같은 일을 해야하는 점이다

C++에서 더 안전한 매크로이므로 버그가 발생하기 쉽습니다 (제 생각에는). 나는 한 줄의 코드 일 뿐이므로 인라인으로 만들었고, 그런 종류의 프로세스를위한 스택 조작은 조금 복잡해 보입니다. 그러나 내가 틀렸다면, 이것으로 나를 교정하십시오.

이제 concatstr() 기능 위에 :

여기서 문제는 최대한 빨리 두 번째 루프에 도착으로 인해 메모리에 2 회 반복시 프로그램 충돌 위반을 읽을 수 있다는 것입니다. 왜 이런 일이 나는 잘 모릅니다. 다음과 같이

호출 코드는 같습니다

내가 여기에 시각적-C++ 태그를 가하고있어 유일한 이유는 내가 바로 C에서처럼 이런 것하고있어 비록 난 것입니다
const size_t len = StrLength(msg) + mPrefix.length() + StrLength("\n\n"); 

char* out = (char*)malloc(sizeof(char) * (len + 1)); 

out[0] = '\0'; 

const char* tmp_pass = mPrefix.c_str(); 

concatstr(&out, &tmp_pass); 
concatstr(&out, &msg); 

VC++를 컴파일러로 사용.

여기에 어떤 문제가 있다고 생각하는 사람이 있습니까?

+1

'StrLength()'이 필요하지 않습니다. 특히 그 기능의 코드를 읽은 후에; 'strlen()'을 직접 사용하십시오. http://en.cppreference.com/w/cpp/language/operator_precedence를 참조하십시오. '[]'는'*'보다 우선시되고, 당신은 그것을 두 곳에서 사용합니다. – foxx1337

답변

2

당신은

tmp[ counter++ ] = *dest[ iDest ]; 

은 (암시 적)이다
tmp[ counter++ ] = *(dest[ iDest ]); 

을 parethesised하지만 당신은 명시 적 괄호

tmp[ counter++ ] = (*dest)[ iDest ]; 

필요 잘못 우선 순위를 가지고 있습니다. 괄호없이

, *dest 참조를 취소 한 후 iDest * sizeof(char*) 바이트의 오프셋에서 (추정) char*은 아마 당신이 역 참조에 허용되는 유효한 char* 없다. *dest이 가리키는 오프셋 후 iDest 바이트의 바이트에 액세스하려고합니다. 끝에

,

strncpy(*dest, tmp, total_len); 

가 연결된 스트링 0 종료되지 않는다. 거기에 totalLenNull이 필요합니다. 이외에도

:

return strnlen(string, strlen(string)); 

오히려 신중하다. 먼저 string을 트래버스하여 0 바이트 종료를 찾은 다음 그 전에 char을 계산합니다. 그런 다음 첫 번째 strlen(string) 바이트 중 0 바이트 종료가 string인지 여부를 확인합니다. string이이 두 호출 사이에서 수정되지 않으면 (그리고 아마도 마주 쳤을 것입니다), 두 번째 호출은 첫 번째 호출과 정확히 동일하게 리턴합니다.