0

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

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

代替:

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

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

事情就是这样。即使在将内部逻辑缩减为绝对不是基于逻辑错误的无限循环之后,循环包含 my printf,它仍然被破坏。

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

我的问题是:

  1. 为什么这会破坏内存?简单地读取垃圾内存会破坏程序的控制结构吗?如果没有,这是否意味着即使 Electric Fence 不再抱怨,我的某个地方仍然存在泄漏?
  2. 我认为它抱怨不存在的属性的原因是因为它符合给定的类型定义,而不是实际存在的内容。既然我已经把它打出来了,这在我的脑海里就不那么可疑了,但我想确认我没有离开这里。
4

2 回答 2

1

欢迎来到 C,在这里,铸造的力量可以让你让任何一段记忆看起来像你想要的任何对象,但风险自负。如果你转换的​​东西不是那个类型的对象,并且那个类型包含一个指向其他东西的指针,你就有崩溃的风险。因为即使尝试读取尚未实际映射到进程虚拟内存地址空间的随机内存也可能导致核心或从没有读取权限的某些内存区域读取也会导致核心,如 NULL 指针。

例子:

#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;
}
于 2013-11-14T06:56:11.717 回答
1

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

此外,在某些嵌入式系统中,尝试读取无效地址可能会产生其他更糟糕的影响,这并不是设计使然,而是偶然发生的。例如,在我设计的一个系统上,我必须连接一个存储设备,该设备在读取周期后离开总线有点慢。如果下一次内存读取是从至少有一个等待状态或在不同总线上的内存区域执行的,则不会有问题。但是,如果在快速外部存储器分区中运行的代码试图读取该区域,则存储器设备未能快速离开总线会损坏下一条获取指令的某些位。所有这一切的最终结果是从位于某些地方的代码访问慢速设备没有问题,

于 2013-11-15T19:39:56.500 回答