简体   繁体   English

gcc中的c内存管理

[英]C memory management in gcc

I am using gcc version 4.7.2 on Ubuntu 12.10 x86_64. 我在Ubuntu 12.10 x86_64上使用gcc版本4.7.2。

First of all these are the sizes of data types on my terminal: 首先是我终端上数据类型的大小:

sizeof(char) = 1    

sizeof(short) = 2          sizeof(int) = 4
sizeof(long) = 8           sizeof(long long) = 8

sizeof(float) = 4          sizeof(double) = 8
sizeof(long double) = 16

Now please have a look at this code snippet: 现在请看一下这段代码:

int main(void)
{   
    char c = 'a';
    printf("&c = %p\n", &c);
    return 0;
}

If I am not wrong we can't predict anything about the address of c . 如果我没有错,我们无法预测c的地址。 But each time this program gives some random hex address ending in f . 但每次这个程序给出一些以f结尾的随机十六进制地址。 So the next available location will be some hex value ending in 0 . 因此,下一个可用位置将是以0结尾的某个十六进制值。 I observed this pattern in case of other data types too. 在其他数据类型的情况下我也观察到了这种模式。 For an int value the address was some hex value ending in c . 对于int值,地址是以c结尾的十六进制值。 For double it was some random hex value ending in 8 and so on. 对于double,它是一些以8结尾的随机十六进制值,依此类推。

So I have 2 questions here. 所以我在这里有两个问题。

1) Who is governing this kind of memory allocation ? 1)谁在管理这种内存分配? Is it gcc or C standard ? 是gcc还是C标准?

2) Whoever it is, Why it's so ? 2)无论是谁,为什么会这样? Why the variable is stored in such a way that next available memory location starts at a hex value ending in 0 ? 为什么变量存储在这样的方式下一个可用的内存位置开始在结尾的十六进制值0 Any specific benefit ? 任何特定的好处?

Now please have a look at this code snippet: 现在请看一下这段代码:

int main(void)
{   
    double a = 10.2;
    int b = 20;
    char c = 30;
    short d = 40;

    printf("&a = %p\n", &a);
    printf("&b = %p\n", &b);
    printf("&c = %p\n", &c);
    printf("&d = %p\n", &d);

    return 0;
}

Now here what I observed is completely new for me. 现在,我观察到的对我来说是全新的。 I thought the variable would get stored in the same order they are declared. 我认为变量将按照它们声明的相同顺序存储。 But No! 但不是! That's not the case. 事实并非如此。 Here is the sample output of one of random run: 以下是随机运行之一的示例输出:

&a = 0x7fff8686a698
&b = 0x7fff8686a694
&c = 0x7fff8686a691
&d = 0x7fff8686a692

It seems that variables get sorted in increasing order of their sizes and then they are stored in the same sorted order but with maintaining the observation 1. ie the last variable (largest one) gets stored in such a way that the next available memory location is an hex value ending in 0 . 似乎变量按其大小的递增顺序排序,然后它们以相同的排序顺序存储,但保持观察1.即最后一个变量(最大的一个)以下一个可用内存位置的方式存储十六进制值,以0结尾。

Here are my questions: 这是我的问题:

3) Who is behind this ? 3)谁支持这个? Is it gcc or C standard ? 是gcc还是C标准?

4) Why to waste the time in sorting the variables first and then allocating the memory instead of directly allocating the memory on 'first come first serve' basis ? 4)为什么要先浪费时间对变量进行排序然后再分配内存而不是直接按“先到先得”的方式分配内存? Any specific benefit of this kind of sorting and then allocating memory ? 这种排序的任何特定好处,然后分配内存?

Now please have a look at this code snippet: 现在请看一下这段代码:

int main(void)
{   
    char array1[] = {1, 2};
    int array2[] = {1, 2, 3};

    printf("&array1[0] = %p\n", &array1[0]);
    printf("&array1[1] = %p\n\n", &array1[1]);

    printf("&array2[0] = %p\n", &array2[0]);
    printf("&array2[1] = %p\n", &array2[1]);
    printf("&array2[2] = %p\n", &array2[2]);

    return 0;
}

Now this is also shocking for me. 现在这对我来说也是令人震惊的。 What I observed is that the array is always stored at some random hex value ending in '0' if the elements of an array >= 2 and if elements < 2 then it gets memory location following observation 1. 我观察到的是,如果数组的elements of an array >= 2并且如果elements < 2那么数组总是存储在以'0'结尾的一些随机十六进制值中,然后它在观察1之后获得存储位置。

So here are my questions: 所以这是我的问题:

5) Who is behind this storing an array at some random hex value ending at 0 thing ? 5)谁在这个存储数组后面的某个随机十六进制值以0结尾? Is it gcc or C standard ? 是gcc还是C标准?

6) Now why to waste the memory ? 6)现在为什么浪费记忆? I mean array2 could have been stored immediately after array1 (and hence array2 would have memory location ending at 2 ). 我的意思是array2可能已经在array1之后立即存储(因此array2内存位置将以2结尾)。 But instead of that array2 is stored at next hex value ending at 0 thereby leaving 14 memory locations in between. 但是,而不是将array2存储在以0结尾的下一个十六进制值,从而在其间留下14个存储器位置。 Any specific benefits ? 任何具体的好处?

The address at which the stack and the heap start is given to the process by the operating system. 堆栈和堆启动的地址由操作系统提供给进程。 Everything else is decided by the compiler, using offsets that are known at compile time. 其他所有内容都由编译器决定,使用编译时已知的偏移量。 Some of these things may follow an existing convention followed in your target architecture and some of these do not. 其中一些可能遵循目标体系结构中遵循的现有约定,而其中一些则不遵循。

The C standard does not mandate anything regarding the order of the local variables inside the stack frame (as pointed out in a comment, it doesn't even mandate the use of a stack at all). C标准没有强制要求任何关于堆栈帧内局部变量的顺序(如注释中所指出的,它甚至根本不要求使用堆栈 )。 The standard only bothers to define order when it comes to structs and, even then, it does not define specific offsets, only the fact that these offsets must be in increasing order. 标准只涉及到结构时定义顺序,即使这样,它也没有定义特定的偏移,只有这些偏移必须按递增顺序排列。 Usually, compilers try to align the variables in such a way that access to them takes as few CPU instructions as possible - and the standard permits that, without mandating it. 通常,编译器会尝试以这样的方式对齐变量:对它们的访问尽可能少地使用CPU指令 - 而标准允许这样做,而不强制它。

Part of the reasons are mandated by the application binary interface (ABI) specifications for your system & processor. 部分原因是由系统和处理器的应用程序二进制接口 (ABI)规范强制实施的。

See the x86 calling conventions and the SVR4 x86-64 ABI supplement (I'm giving the URL of a recent copy; the latest original is surprisingly hard to find on the Web). 请参阅x86调用约定SVR4 x86-64 ABI补充 (我给出了最新副本的URL;最新的原始文件在Web上很难找到)。

Within a given call frame, the compiler could place variables in arbitrary stack slots. 在给定的调用帧内,编译器可以将变量放在任意堆栈槽中。 It may try (when optimizing) to reorganize the stack at will, eg by decreasing alignment constraints. 它可以尝试(在优化时)随意重组堆栈,例如通过减少对齐约束。 You should not worry about that. 你不应该担心这一点。

A compiler try to put local variables on stack location with suitable alignment. 编译器尝试将局部变量放在具有适当对齐的堆栈位置上。 See the alignof extension of GCC. 请参阅GCC的alignof扩展。 Where exactly the compiler put these variables is not important, see my answer here . 编译器确切地放置这些变量并不重要,请参阅我的答案 (If it is important to your code, you really should pack the variables in a single common local struct , since each compiler, version and optimization flags could do different things; so don't depend on that precise behavior of your particular compiler). (如果它对您的代码很重要,那么您真的应该将变量打包在一个公共的本地struct ,因为每个编译器,版本和优化标志可以做不同的事情;所以不要依赖于特定编译器的精确行为)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM