0

私はある種のC-String連結を行う必要がある状況にあるので、それを自分で学ぶことにしました(これは単なる個人的なプロジェクトなので、私は世界中にずっといます)。

これまでのところ、これら2つの関数を考え出しました(以下に説明を示します)。

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 ++ではより安全なマクロのように機能するはずなので、バグが発生しにくいということです(私は思います)。たった1行のコードなので、インラインにしました。そのようなプロセスのスタック操作は少し多いようです。しかし、私が間違っている場合は、これについて訂正してください。

次に、concatstr()関数に移ります。

ここでの問題は、2番目のループに到達するとすぐに、メモリ読み取り違反のために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++を使用しているためです。

誰かがここで問題が何であるかについての考えを持っていますか?

4

1 に答える 1

2

優先順位が間違っている、

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

(暗黙的に) 括弧で括られている

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

しかし、あなたは必要です

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

明示的な括弧付き。

かっこがないと、逆参照された後のバイトchar*のオフセットにある (推定) は、おそらく逆参照が許可されている有効なものではありません。何を指すかの後のバイトのオフセットでバイトにアクセスしたい。iDest * sizeof(char*)*destchar*iDest*dest

最後に、

strncpy( *dest, tmp, total_len );

連結された文字列を 0 で終了しません。そこが必要ですtotalLenNull

余談:

return strnlen( string, strlen( string ) );

かなり慎重です。最初にトラバースして終端の 0 バイトを見つけ、その前に s をstring数えます。次に、 の最初のバイトにchar終端の 0 バイトがあるかどうかを確認します。これら 2 つの呼び出しの間で が変更されていない限り(そしておそらくあなたはうんざりしています)、2 番目の呼び出しは最初の呼び出しとまったく同じものを返します。strlen(string)stringstring

于 2012-12-01T23:23:15.600 に答える