2012-12-01 102 views
0

我有点需要做一些C字符串连接的情况,所以我决定把它放在我自己的学习上(这只是一个个人项目,所以我拥有所有的在世界上的时间,真的)。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次迭代由于内存的程序崩溃读冲突。为什么发生这种情况我不确定。

调用代码如下:

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

我把视觉-C++标签这里的唯一原因是,即使我像一个这样做会在直C,我使用VC++作为编译器。

有没有人有这个问题的想法?

+1

你不需要'StrLength()';特别是在阅读该函数的代码之后;直接使用'strlen()'。请参阅http://en.cppreference.com/w/cpp/language/operator_precedence。 '[]'优先于'*',并在2个地方使用它。 – foxx1337

回答

2

你有优先级错误,

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

(隐含)parethesised

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

,但你需要

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

有明确的括号。

如果没有括号,在该(假设)char**dest解除引用后的iDest * sizeof(char*)字节偏移,有可能是无效char*你有权取消引用。您想要在*dest指向的位置之后以iDest字节的偏移量访问该字节。

最后,

strncpy(*dest, tmp, total_len); 

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

旁白:

return strnlen(string, strlen(string)); 

是相当谨慎。首先遍历string找到终止的0字节,在此之前计数为char s。然后检查string的第一个strlen(string)字节中是否有终止0字节。除非在这两个调用之间修改了string(然后您可能会被调整),否则第二个将返回与第一个调用完全相同的值。