填充了未声明的结构数组

时间:2012-03-12 00:49:31

标签: c struct malloc

当我注意到我的代码中有关于数组大小的错误时,我一直在对我编写的一些代码进行一些测试,但程序仍然正常运行。 这里有一些简化的代码可以让您了解正在发生的事情。

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>

typedef struct
{
int score;
}player;

void printScore(player *p, int num);

int main(void)
{

    printf ("\nEnter number of players (1 - 4)\n");
    scanf ("%d", &numPlayers);

    player *p = (player*)malloc(sizeof(player) * 3);

    for (i=0;i<numPlayers;i++)
    {
        printScore(p, i);
    }

}

void printScore(player *p, int num)
{

        p[num].score = 1;
        printf ("%d\n", p[num].score);
}

malloc函数中的3实际上应该是numPlayers。 如果我将它保留为3,并在菜单中输入更高的数字,程序通常会崩溃,但它有时会起作用。怎么可能? 如果我只为p [0],p [1],p [2]保留了足够的内存,那么(例如)p [15] .score如何被填充?

4 个答案:

答案 0 :(得分:1)

它被称为“未定义的行为”。当行为未定义时 - 一切皆有可能。访问无效指针(如示例中所示)是标准未定义程序行为的许多情况之一,编译器可以随心所欲地执行任何操作。

在这种情况下,任何行为都是正确的行为。在您的情况下,编译器不执行任何操作,程序运行,就好像分配了内存一样。如果操作系统没有因此而杀死你(=程序在访问冲突时崩溃) - 这是你纯粹的运气。

答案 1 :(得分:0)

在C代码中,您应该记住您正在操作实际内存,编译器不会帮助您检查无效的内存访问。

p是堆上的指针,p的长度为3 * sizeof(播放器),但在此之后,内存可能仍然存在,但该值是不可预测的。

答案 2 :(得分:0)

在预约记忆中就是 - 预订。它不对实际分配的内容设置限制,它只保证您请求的空间是为您的使用保留的。您的程序开始阅读正确的内容,然后继续阅读您无权访问的内存内容。内存管理器可能会让你继续读取内存。 C不保护您不这样做。您需要知道已分配的内容以及允许阅读的内容。

正如其他人可能会说的那样,读取已分配空间的末尾是未定义的行为,这意味着任何事情都可能发生。在大多数情况下,你会看到非常合理的事情。

答案 3 :(得分:0)

内存中的程序映射可以组织为例如:(text + data + bss)

此映射在编译时建立,并且在执行期间保持不变,在使用动态分配malloc()时,程序可以在运行时扩展到虚拟内存的未占用部分。

您的计划: 1-在运行时,它在内存(HEAP)中分配3个内存段。

2- p由malloc初始化,堆中的地址为NNNN。它是分配的第3组第一组的位置。 第一个地址(p + 0 *(sizeof(玩家)),第二个地址为(p + 1 *(sizeof(玩家)),第三个地址为(p + 2 *(sizeof(玩家))。

使用C,您可以尝试访问任何您想要的地方,但是您可以安装安全机制,以免损坏您的代码,数据或某些非保护区域。 在这种情况下安全机制的示例:在3 * sizeof或测试用户的输入中使用numPlayers * sizeof而不是常量“3”。

因此对p [15]的任何读/写访问都将定向到(p + 15 *(sizeof(player)))。

3-为什么要填充? 内存可能包含程序中的其他数据或噪音。这就是填充结构字段的原因。

4-为什么这是随机的崩溃? 您的写访问权限会破坏数据,但可能不会崩溃。如果你在记忆中走向TEXT段。你会破坏你的代码,你肯定会崩溃。