0

我有点需要做一些 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()功能:

这里的问题是,一旦我进入第二个循环,由于内存读取冲突,程序在第二次迭代时崩溃。为什么会发生这种情况我不确定。

调用代码如下所示:

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*)字节偏移后被*dest取消引用,可能没有char*允许您取消引用的有效值。您希望在指向iDest后的字节偏移处访问字节。*dest

在最后,

strncpy( *dest, tmp, total_len );

不会 0 终止连接的字符串。你需要totalLenNull那里。

在旁边:

return strnlen( string, strlen( string ) );

比较谨慎。首先,您遍历string找到终止的 0 字节,char在此之前计数 s。然后检查strlen(string). string除非string在这两个调用之间进行了修改(然后您可能会被冲洗掉),否则第二个调用将返回与第一个调用完全相同的结果。

于 2012-12-01T23:23:15.600 回答