C Функция конкатенации строк

Я как бы в ситуации, когда мне нужно сделать некоторую конкатенацию C-String, поэтому я решил взять на себя обучение (это всего лишь личный проект, поэтому у меня есть все время в мире, на самом деле).

До сих пор я придумал эти две функции (объяснение приведено ниже):

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-й итерации из-за нарушения чтения памяти. Почему это происходит, я не уверен.

Код вызова выглядит следующим образом:

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 );

Единственная причина, по которой я помещаю здесь тег visual-C++, заключается в том, что, хотя я делаю это так же, как в прямом C, я использую VC++ в качестве компилятора.

Кто-нибудь знает, в чем здесь проблема?


person zeboidlund    schedule 01.12.2012    source источник
comment
Вам не нужно StrLength(); особенно после прочтения кода этой функции; используйте strlen() напрямую. См. en.cppreference.com/w/cpp/language/operator_precedence. [] имеет приоритет над *, и вы используете его в двух местах.   -  person foxx1337    schedule 02.12.2012


Ответы (1)


У вас неправильный приоритет,

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

(неявно) заключено в скобки

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

но тебе нужно

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

с явными скобками.

Без круглых скобок (предполагаемый) char* со смещением iDest * sizeof(char*) байтов после разыменования *dest, вероятно, нет действительного char*, который вам разрешено разыменовывать. Вы хотите получить доступ к байту со смещением iDest байтов после того, на что указывает *dest.

В конце,

strncpy( *dest, tmp, total_len );

не завершает конкатенированные строки 0. Вам нужно totalLenNull там.

В стороне:

return strnlen( string, strlen( string ) );

довольно осмотрителен. Сначала вы проходите string, чтобы найти завершающий 0-байт, считая до этого chars. Затем вы проверяете, есть ли завершающий 0-байт среди первых strlen(string) байтов string. Если string не будет изменено между этими двумя вызовами (и тогда вас, вероятно, облили шлангом), второй вызов вернет то же самое, что и первый вызов.

person Daniel Fischer    schedule 01.12.2012