char *大小与malloc之后的预期不同

时间:2012-10-23 00:52:59

标签: objective-c c arrays memory char

我已经创建了下一个代码来获取 char * ,但是在执行此代码之后,finalResult的大小比预期的大,带有一些垃圾字符。为什么??我该如何解决?

//returns void
void processChar(){
            //.... more stuff here
            // init is a previous char*
            char* end = strstr(init,"</div>");
            if(end != NULL){
                    long length = strlen(init) - strlen(end);
                    if (length > 0){
                            char* finalResult = malloc(length);
                            strncat(finalResult, init,length);
                            //these lengths are different,being strlen(finalResult) > length
                            NSLog(@"%d %d",strlen(finalResult),length);
                            //... more stuff here  
                    }
            }
            return;
}

2 个答案:

答案 0 :(得分:6)

此代码:

char* finalResult = malloc(length);
strncat(finalResult, init,length);

会给你一个未定义的结果。您尝试将finalResultinit连接起来,即使您从未初始化finalResult。也许您打算使用strncpy()代替strncat()

此外,finalResult还不够大;它还需要保存终止\0字符,因此您应该使用:

进行分配
char* finalResult = malloc(length + 1);

此外,正如Keith Thomson所指出的,当你使用它时要小心dangers of strncpy()

在这种特殊情况下,您可以通过在分配strncpy()后将finalResult初始化为空字符串来避免使用strncat(),然后像以前一样使用char* finalResult = malloc(length + 1); finalResult[0] = '\0'; strncat(finalResult, init, length);

malloc()

当然,您还应检查{{1}}的返回值是否存在内存不足错误,但这不在您的问题范围内。

答案 1 :(得分:0)

来自man strlen:

The strlen() function calculates the length of the string s, not including the terminating '\0' character.

显然你的malloc需要为终止'\ 0'字符分配空间。所以修复很简单。在malloc中分配长度+ 1个字节。

您的代码中存在第二个严重错误。 Malloc将返回未初始化的内存,但strncat将附加到现有字符串。因此,它将首先在未初始化的内存中搜索第一个'\ 0',这不是你想要的。所以strncat实际上取决于malloc返回的第一个字节是'\ 0'。你想改用strncpy。

修复了错误的代码:

char * end = strstr(init, "</div>");
if (end != NULL) {
    long length = strlen(init) - strlen(end);
    if (length > 0) {
        char * finalResult = malloc(length+1);
        strncpy(finalResult, init, length);
        printf("strlen(finalResult) = %ld, length = %ld\n", strlen(finalResult), length);
        free(finalResult);
    }
}