c-GCC不同的实际内存分配量,然后我分配给程序中的变量


#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int value = 5;
char buffer_one[9], buffer_two[9];
strcpy(buffer_one, "one"); /* Put "one" into buffer_one. */
strcpy(buffer_two, "two"); /* Put "two" into buffer_two. */
printf("[BEFORE] buffer_two is at %p and contains '%s'n", buffer_two, buffer_two);
printf("[BEFORE] buffer_one is at %p and contains '%s'n", buffer_one, buffer_one);
printf("[BEFORE] value is at %p and is %d (0x%08x)n", &value, value, value);
printf("n[STRCPY] copying %d bytes into buffer_twonn", strlen(argv[1]));
strcpy(buffer_two, argv[1]); /* Copy first argument into buffer_two. */
printf("[AFTER] buffer_two is at %p and contains '%s'n", buffer_two, buffer_two);
printf("[AFTER] buffer_one is at %p and contains '%s'n", buffer_one, buffer_one);
printf("[AFTER] value is at %p and is %d (0x%08x)n", &value, value, value);
}

输出1:-我给buffer_two变量24字节的数据,它接受它,但我只给buffer_two分配了9字节的内存。并且,为什么buffer_twobuffer_one之间的地址差是16而不是9。

ubuntus@ubuntus:~$ ./sample2 123456789012345678901234
[BEFORE] buffer_two is at 0x7ffe29136510 and contains 'two'
[BEFORE] buffer_one is at 0x7ffe29136500 and contains 'one'
[BEFORE] value is at 0x7ffe291364fc and is 5 (0x00000005)
[STRCPY] copying 24 bytes into buffer_two
[AFTER] buffer_two is at 0x7ffe29136510 and contains '123456789012345678901234'
[AFTER] buffer_one is at 0x7ffe29136500 and contains 'one'
[AFTER] value is at 0x7ffe291364fc and is 5 (0x00000005)

输出2:-

ubuntus@ubuntus:~$ ./sample2 1234567890123456789012345
[BEFORE] buffer_two is at 0x7fff51549fe0 and contains 'two'
[BEFORE] buffer_one is at 0x7fff51549fd0 and contains 'one'
[BEFORE] value is at 0x7fff51549fcc and is 5 (0x00000005)
[STRCPY] copying 25 bytes into buffer_two
[AFTER] buffer_two is at 0x7fff51549fe0 and contains '1234567890123456789012345'
[AFTER] buffer_one is at 0x7fff51549fd0 and contains 'one'
[AFTER] value is at 0x7fff51549fcc and is 5 (0x00000005)
*** stack smashing detected ***: ./sample2 terminated
Aborted (core dumped)

关于此:

我将24字节的数据提供给buffer_two变量,它是接受

正如评论中已经提到的,这是未定义行为的典型案例。C不检查数组的边界,而是由程序员来处理。如果数组的边界被破坏,任何事情都可能发生。您可能会意外地写入其他变量的数据,或者程序可能崩溃,或者有时它可能会工作(就像您的情况一样(。

当我运行你的代码时,我得到的输出是:

nandan@debian:~$ ./sample 123456789012345678901234 
[BEFORE] buffer_two is at 0x7ffc2db1e19a and contains 'two'
[BEFORE] buffer_one is at 0x7ffc2db1e1a3 and contains 'one'
[BEFORE] value is at 0x7ffc2db1e1ac and is 5 (0x00000005)
[STRCPY] copying 24 bytes into buffer_two
[AFTER] buffer_two is at 0x7ffc2db1e19a and contains '1234567890123456789012345'
[AFTER] buffer_one is at 0x7ffc2db1e1a3 and contains '0123456789012345'
[AFTER] value is at 0x7ffc2db1e1ac and is 842084409 (0x32313039)

当我们比较我和你们的产出时,可以注意到很多事情。

首先,我们的两个程序都没有崩溃。万岁!

其次,请注意,在您的输出中,首先分配给buffer_one内存,然后分配给buffer_two(因此,buffer_two的地址比buffer_one的地址高。这很明显,对吧?它们是按照代码中声明的顺序分配的(。但是,在我的情况下,首先分配buffer_two,然后分配buffer_one(请注意,在我输出中,buffer_two的地址低于buffer_one(。那么,为什么在我的情况下会发生这种情况呢?这是一个依赖编译器的特性。自动变量在堆栈上的分配顺序完全由编译器决定。我不知道为什么会发生这种情况,但我想这与优化有关。点击此处了解更多信息。

第三,由于在我的情况下buffer_two的地址低于buffer_one,所以在复制9字节buffer_two中的24字节字符串时,可以注意到未定义的行为。buffer_one正在被覆盖!![AFTER] buffer_one is at 0x7ffc2db1e1a3 and contains '0123456789012345'

现在,关于这个:

然而,我只为buffer_two分配了9字节的内存。为什么buffer_two和buffer_one之间的地址差是16,而不是9.

请注意,在我的案例中,GCC为buffer_one和buffer_two分配了精确的9个字节。

通常,GCC会尝试将自动变量对齐到堆栈上的2^n个字节,以提高性能,即使它为此牺牲了几个字节。默认情况下,n=4。因此,在您的情况下,为9字节数组分配了16(2^4(个字节,其余7个字节用空字符填充。

您可以在GCC中使用-mpreferred-stack-boundary标志来更改此对齐方式。阅读文档或搜索SO上关于该标志使用的其他问题。

相关内容

最新更新