使用char *时的奇怪行为

时间:2017-11-21 14:20:01

标签: c

我有这个功能

Function *function_get_by_label(char *label_name) {     
    int new_len = strlen(label_name) - 9;
    char* name = malloc(sizeof(char) * new_len);
    for (int i = 0; i < new_len; i++) {
        name[i] = label_name[i];
    }

    return function_get(name);
}

但是,当我尝试使用gdb调试这个时,比如显示name变量,我得到以下内容

(gdb) display name
1: name = 0x610120 ""
(gdb) n
1: name = 0x610120 ""
1: name = 0x610120 "m"
1: name = 0x610120 "m"
1: name = 0x610120 "mu"
1: name = 0x610120 "mu"
1: name = 0x610120 "mul"
1: name = 0x610120 "mul"
1: name = 0x610120 "mult"
1: name = 0x610120 "mult"
1: name = 0x610120 "multi"
1: name = 0x610120 "multi"
1: name = 0x610120 "multip"
1: name = 0x610120 "multip"
1: name = 0x610120 "multipl"
1: name = 0x610120 "multipl"
1: name = 0x610120 "multiply2_function"

这怎么可能有这么奇怪的行为? 我试图用这些mallocs操纵。我也尝试重写这个函数,这样我就可以举例说明如何重现它,但没有成功。

更奇怪的是,当我将malloc中的已分配空间更改为sizeof(char) * 99时,结果是

(gdb) display name
1: name = 0x60f120 ""
(gdb) n
1: name = 0x60f120 ""
1: name = 0x60f120 "m"
1: name = 0x60f120 "m"
1: name = 0x60f120 "mu"
1: name = 0x60f120 "mu"
1: name = 0x60f120 "mul"
1: name = 0x60f120 "mul"
1: name = 0x60f120 "mult"
1: name = 0x60f120 "mult"
1: name = 0x60f120 "multi"
1: name = 0x60f120 "multi"
1: name = 0x60f120 "multip"
1: name = 0x60f120 "multip"
1: name = 0x60f120 "multipl"
1: name = 0x60f120 "multipl"
1: name = 0x60f120 "multiplyltiply2_function"

2 个答案:

答案 0 :(得分:2)

将字符串label_name复制到一个缩短了9个字符的新变量name。你复制所有字符减去最后9个字符。

此时,name是未终止的C字符串,并且已使用其所有存储空间。在机器的内存中,name之后会有更多的内存,但它不是你的,可以有任何数据。实际上,在您复制了最后一个字符后(并且您的malloced内存被纯粹的机会归零),您会看到不在您内存中的内容。

您将name传递给函数function_get,但该函数并不知道name的长度。如果它会打印它,它可以正确打印name,或者可以在它之后打印任何数据,直到它遇到空字符(如果它遇到一个;你不要&#39 ;知道那里有什么)。这就是所谓的未定义行为

当您使用malloc分配99个字符时,您说它仍然显示&#34;奇怪的行为&#34;。实际上,因为malloc没有初始化内存,所以内存中可能有任何数据。虽然内存现在是你的(直到char 99),你仍然没有用\0字符终止字符串,你仍然有未定义的行为

获得的经验教训:终止您的字符串 \0 !!

答案 1 :(得分:0)

你永远不会空终止name,也不会为空终止符分配足够的空间。此外,没有必要循环并通过这种方式复制字符。由于我们知道源字符串大于我们复制的长度,因此您应该能够做一个简单的memcpy(否则strncpy将是一个不错的选择)。所以也许看起来像这样:

Function *function_get_by_label(char *label_name) {     
    int new_len = strlen(label_name) - 8;
    char* name = malloc(sizeof(char) * new_len);
    memcpy(label_name, name, new_len-1);
    name[new_len-1] = '\0';

    return function_get(name);
}