我处于一种需要进行一些 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()
函数:
这里的问题是,一旦我进入第二个循环,程序就会由于内存读取冲突而在第二次迭代时崩溃。我不确定为什么会发生这种情况。
调用代码如下:
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++ 作为编译器。
有人知道这里的问题是什么吗?
最佳答案
你的优先顺序错了,
tmp[ counter++ ] = *dest[ iDest ];
(隐式)括号化
tmp[ counter++ ] = *(dest[ iDest ]);
但你需要
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
。然后检查 string
的前 strlen(string)
字节中是否存在终止 0 字节。除非 string
在这两个调用之间进行了修改(然后您可能会被淘汰),否则第二个调用将返回与第一个调用完全相同的结果。
关于C字符串连接问题函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13664690/