简体   繁体   English

C 语言中 memory 分配的本地和全局数组有什么区别?

[英]What is difference for local and global array for memory allocation in C language?

I have written a program for checking array out of bounds for global array and local array.我编写了一个程序来检查全局数组和本地数组的数组越界。

Case 1:情况1:

/* Local and global Aoob demo*/

uint8  problematic_array_global[5] = {22,34,65,44,3};
uint16 adjacent_array_global[3] = {82,83,84};

void aoob_example()
{
/*Global*/
    printf("            Before global Aoob , adjacent_array={%u,%u,%u}\n",adjacent_array_global[0],adjacent_array_global[1],adjacent_array_global[2]);
    
    uint8 idx = 0;
    
    for(;idx < 15;idx++)
    {
        problematic_array_global[idx] = idx;
    
    }
    printf("            After global Aoob  , adjacent_array={%u,%u,%u}\n",adjacent_array_global[0],adjacent_array_global[1],adjacent_array_global[2]);

And got the result:并得到了结果:

Before global Aoob , adjacent_array_global={82,83,84}
After global Aoob  , adjacent_array_global={2312,2826,3340}

Case 2:案例二:

void aoob_example()
{
    uint8 problematic_array[5] = {1,2,3,4,5};
    uint8 adjacent_array[3] = {12,13,14};
    
    printf("            Before Aoob var=%u , adjacent_array={%u,%u,%u}\n",var,adjacent_array[0],adjacent_array[1],adjacent_array[2]);
    uint8 idx = 0;
    
    for(;idx < 8; idx++)
    {
        problematic_array[idx] = idx;
    
    }
    printf("            After Aoob var =%u , adjacent_array={%u,%u,%u}\n",var,adjacent_array[0],adjacent_array[1],adjacent_array[2]);

And got the result:并得到了结果:

Before Aoob var=10 , adjacent_array = {12,13,14}
After Aoob var =10 , adjacent_array = {12,13,14}

Seems with local array we didn't have any array out of bounds although I have declared 2 local arrays nearby and for loop up to 8 iteration.尽管我已经在附近声明了 2 个本地 arrays 并且 for 循环最多 8 次迭代,但似乎使用本地数组我们没有任何超出范围的数组。

What is difference between 2 declaration? 2声明有什么区别? How is an array stored in memory in this program?这个程序中memory中的数组是如何存储的? What happened here?这里发生了什么? How to understand this behavior in c?如何理解 c 中的这种行为?

Out of two nearby arrays, only one will overwrite the other when out of bounds.在附近的两个 arrays 中,只有一个会在超出范围时覆盖另一个。 The order of that adjacency is not defined.该邻接的顺序未定义。

That is one factor.这是一个因素。 The other is is the compiler optimization, and the warnings.另一个是编译器优化和警告。 With global arrays and -O1 I get:使用全局-O1和 -O1 我得到:

 mov    BYTE PTR [rip+0x2ec6],0x0        # 4030 <problematic_array>
 mov    BYTE PTR [rip+0x2ec0],0x1        # 4031 <problematic_array+0x1>
 mov    BYTE PTR [rip+0x2eba],0x2        # 4032 <problematic_array+0x2>
 mov    BYTE PTR [rip+0x2eb4],0x3        # 4033 <problematic_array+0x3>
 mov    BYTE PTR [rip+0x2eae],0x4        # 4034 <problematic_array+0x4>
 mov    BYTE PTR [rip+0x2ea8],0x5        # 4035 <adjacent_array>
 mov    BYTE PTR [rip+0x2ea2],0x6        # 4036 <adjacent_array+0x1>
 mov    BYTE PTR [rip+0x2e9c],0x7        # 4037 <adjacent_array+0x2>

So the compiler knows exactly what is happening, and there is a warning:所以编译器确切地知道发生了什么,并且有一个警告:

warning: iteration 5 invokes undefined behavior

When problematic_array is not writing into adjacent , it writes to whatever else is there, with whatever consequences.problematic_array不写入adjacent ,它会写入任何其他内容,无论后果如何。

With local arrays, the stack region will be involved (stack smashing detected), but the basic problem is the same.使用本地 arrays 会涉及堆栈区域(检测到堆栈粉碎),但基本问题是相同的。 Anything could be overwritten.任何东西都可能被覆盖。

Here the compiler is given a chance to warn because of the constant numbers.在这里,编译器有机会发出警告,因为是常数。 Normally a ooB is more subtle and not easily predictable be the compiler.通常,ooB 更微妙,并且编译器不易预测。

With local arrays带本地 arrays

Accessing problematic_array with index 5 is invalid.访问索引为5problematic_array是无效的。 The array is accessed "out-of-bounds".数组被“越界”访问。 The array has a size of 5 , so you can access elements with indexes 0 to 4 .该数组的大小为5 ,因此您可以访问索引04的元素。

How to understand this behavior in c?如何理解 c 中的这种行为?

This class of behavior is called "undefined behavior".这种 class 的行为称为“未定义行为”。 The behavior of your code is not defined , no one knows what should happen, anything can happen, nothing can happen.您的代码的行为没有定义,没有人知道应该发生什么,任何事情都可能发生,什么都不会发生。 The term "undefined behavior" should be easy to google and even is on wiki - you can learn more from Undefined, unspecified and implementation-defined behavior .术语“未定义的行为”应该很容易用谷歌搜索,甚至在 wiki 上 - 您可以从未定义、未指定和实现定义的行为中了解更多信息。


What is difference for local and global array for memory allocation in C language? C 语言中 memory 分配的本地和全局数组有什么区别?

The difference is in variable scope (global arrays can be accessed from anywhere) and lifetime (global array are alive for the duration of the program, while local arrays are alive till the end of the block).不同之处在于变量 scope(全局 arrays 可以从任何地方访问)和生命周期(全局数组在程序期间处于活动状态,而本地 arrays 一直活动到块结束)。 See https://en.cppreference.com/w/c/language/scope and https://en.cppreference.com/w/c/language/lifetime .请参阅https://en.cppreference.com/w/c/language/scopehttps://en.cppreference.com/w/c/language/lifetime

Well, in this specific case, it affects in some way the code generated by the compiler.好吧,在这种特定情况下,它会以某种方式影响编译器生成的代码。 The only way to find out is to inspect the generated machine code.找出答案的唯一方法是检查生成的机器代码。

What is difference between 2 declaration? 2声明有什么区别?

In the first case, variables are defined at file scope and one is uint16 .在第一种情况下,变量在文件 scope 中定义,其中一个是uint16

In the second, both are uint8 and are defined at block scope.在第二个中,两者都是uint8并在块 scope 中定义。

Do not use uint8 uint16 - use standardized uint8_t and uint16_t from standardized stdint.h .不要使用uint8 uint16 - 使用标准化stdint.h中的标准化uint8_tuint16_t https://en.cppreference.com/w/c/types/integer https://en.cppreference.com/w/c/types/integer

How is an array stored in memory in this program?这个程序中memory中的数组是如何存储的?

Consecutive array elements are guaranteed to be allocated in consecutive adjacent memory locations.保证连续的数组元素被分配在连续相邻的 memory 位置。

There is no relation between these two arrays.这两个 arrays 之间没有关系。 They are unrelated to each other, except they are defined close in the source code.它们彼此无关,除了它们在源代码中的定义很接近。

What happened here?这里发生了什么?

Your code is invalid, and the compiler is generating code.您的代码无效,编译器正在生成代码。 In the first case it "happened" that the compiler generated instructions that overwrote the other array, in the second case it did not happened.在第一种情况下,编译器“发生”了覆盖另一个数组的指令,而在第二种情况下,它没有发生。 You can only inspect the generated by the compiler machine code and go line by line to find out what really happens.您只能逐行检查编译器生成的机器代码和 go 以找出真正发生的情况。

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

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