可以阅读垃圾内存中断程序流吗?

时间:2013-11-14 05:52:46

标签: c memory-management struct linked-list heap-corruption

在我的应用程序中,我有一对嵌套的循环,它们遵循类似嵌套的链表,以便解析数据。我做了一个愚蠢的错误并将一个结构转换为子结构,EG:

if (((ENTITY *) OuterEntityLoop->data)->visible == true) {

而不是:

if (((ENTITY_RECORD *) OuterEntityLoop->data)->entity->visible == true) {

这导致了一个问题,大约70%的运行会导致应用程序完全停止 - 不会崩溃,只是坐着和旋转。程序流程中的诊断printf将以奇数顺序触发或根本不触发,虽然它在大多数情况下自发恢复了几次,但它打破了应用程序。

所以这就是事情。即使在将内部逻辑削减为绝对不是基于逻辑错误的无限循环之后,只有循环 包含我的printf,它仍然被打破。< / p>

第二件事:当结构被错误识别时,如果我试图访问不存在的属性,它仍然会抱怨,即使它没有现存的属性。

我的问题是:

  1. 为什么这个腐败的记忆?可以简单地读取垃圾内存垃圾程序的控制结构?如果没有,这是否意味着即使电围栏不再抱怨我仍然在某处泄漏?
  2. 我认为它抱怨不存在的属性的原因是因为它取决于给定的类型定义,而不是实际存在的类型。现在我已经把它打出来了,这在我的脑海中不那么值得怀疑,但我想确认一下我不在这里。

2 个答案:

答案 0 :(得分:1)

欢迎来到C,在这里,施放的力量,让你可以让任何一块内存看起来像你想要的任何物体,但风险自负。如果您投射的内容实际上不是该类型的对象,并且该类型包含指向其他内容的指针,则存在崩溃的风险。因为即使尝试读取尚未实际映射到进程虚拟内存地址空间的随机内存也可能导致内核或从没有读取权限的内存区域读取也会导致内核,如NULL指针。 / p>

示例:

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

struct foo
{
    int x;
    int y;
    int z;
};

struct bar
{
    int x;
    int y;
    struct foo *p;
};

void evil_cast(void *p)
{
    /* hmm... maybe this is a bar pointer */
    struct bar *q = (struct bar *)p;
    if (q != NULL) /* q is some valid pointer */
    {
        /* as long as q points readable memory q->x will return some value, */
        /* this has a fairly high probability of success */
        printf("random pointer to a bar, x value x(%d)\n", q->x);
        /* hmm... lets use the foo pointer from my random bar */
        if (q->p != NULL)
        {
            /* very high probabilty of coring, since the likely hood that a */
            /* random piece of memory contains a valid address is much lower */
            printf("random value of x from a random foo pointer, from a random bar pointer x value x(%d)\n", q->p->x);
        }

     }
}

int main(int argc, char *argv[])
{
    int *random_heap_data = (int *)malloc(1024); /* just random head memory */
    /* setup the first 5 locations to be some integers */
    random_heap_data[0] = 1;
    random_heap_data[1] = 2;
    random_heap_data[2] = 3;
    random_heap_data[3] = 4;
    random_heap_data[4] = 5;
    evil_cast(random_heap_data);
    return 0;
}

答案 1 :(得分:1)

当程序访问无效内存时,即使是阅读,也无法确定会发生什么。在某些系统上,任何内存读取操作都将有效或导致程序立即崩溃,但在其他系统上,错误读取可能会被误解为执行某些操作的信号。您没有指定您使用的是PC还是嵌入式系统,但是在嵌入式系统上,通常会有许多设计地址在读取时触发各种操作[例如,从串行端口出列接收数据,或确认中断];错误地读取这样的地址可能会导致串行数据丢失,或者可能导致中断控制器认为中断实际上没有处理过。

此外,在某些嵌入式系统中,尝试读取无效地址可能会产生其他更糟糕的影响,这些影响实际上不是设计上的,而是偶然的。例如,在我设计的一个系统上,我必须连接一个存储器设备,这个存储器设备在读取周期后有点慢下车。如果下一次存储器读取是从具有至少一个等待状态或位于不同总线上的存储区域执行的,则没有问题。但是,如果在快速外部存储器分区中运行的代码试图读取该区域,则存储器设备快速离开总线的故障将破坏下一个取出的指令的某些位。所有这些的净效果是从位于某些地方的代码访问慢速设备没有问题,但是有意或无意地从位于快速分区中的代码访问它会导致奇怪且不可重现的故障。