繁体   English   中英

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

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

我编写了一个程序来检查全局数组和本地数组的数组越界。

情况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]);

并得到了结果:

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

案例二:

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]);

并得到了结果:

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

尽管我已经在附近声明了 2 个本地 arrays 并且 for 循环最多 8 次迭代,但似乎使用本地数组我们没有任何超出范围的数组。

2声明有什么区别? 这个程序中memory中的数组是如何存储的? 这里发生了什么? 如何理解 c 中的这种行为?

在附近的两个 arrays 中,只有一个会在超出范围时覆盖另一个。 该邻接的顺序未定义。

这是一个因素。 另一个是编译器优化和警告。 使用全局-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>

所以编译器确切地知道发生了什么,并且有一个警告:

warning: iteration 5 invokes undefined behavior

problematic_array不写入adjacent ,它会写入任何其他内容,无论后果如何。

使用本地 arrays 会涉及堆栈区域(检测到堆栈粉碎),但基本问题是相同的。 任何东西都可能被覆盖。

在这里,编译器有机会发出警告,因为是常数。 通常,ooB 更微妙,并且编译器不易预测。

带本地 arrays

访问索引为5problematic_array是无效的。 数组被“越界”访问。 该数组的大小为5 ,因此您可以访问索引04的元素。

如何理解 c 中的这种行为?

这种 class 的行为称为“未定义行为”。 您的代码的行为没有定义,没有人知道应该发生什么,任何事情都可能发生,什么都不会发生。 术语“未定义的行为”应该很容易用谷歌搜索,甚至在 wiki 上 - 您可以从未定义、未指定和实现定义的行为中了解更多信息。


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

不同之处在于变量 scope(全局 arrays 可以从任何地方访问)和生命周期(全局数组在程序期间处于活动状态,而本地 arrays 一直活动到块结束)。 请参阅https://en.cppreference.com/w/c/language/scopehttps://en.cppreference.com/w/c/language/lifetime

好吧,在这种特定情况下,它会以某种方式影响编译器生成的代码。 找出答案的唯一方法是检查生成的机器代码。

2声明有什么区别?

在第一种情况下,变量在文件 scope 中定义,其中一个是uint16

在第二个中,两者都是uint8并在块 scope 中定义。

不要使用uint8 uint16 - 使用标准化stdint.h中的标准化uint8_tuint16_t https://en.cppreference.com/w/c/types/integer

这个程序中memory中的数组是如何存储的?

保证连续的数组元素被分配在连续相邻的 memory 位置。

这两个 arrays 之间没有关系。 它们彼此无关,除了它们在源代码中的定义很接近。

这里发生了什么?

您的代码无效,编译器正在生成代码。 在第一种情况下,编译器“发生”了覆盖另一个数组的指令,而在第二种情况下,它没有发生。 您只能逐行检查编译器生成的机器代码和 go 以找出真正发生的情况。

暂无
暂无

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

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