-1

据我所知,C/C++ 中的近指针(或远指针)的地址值比 RAM 中的实际地址非常小。所以,如果我继续增加一个指针(比如 int 类型或任何对象类型指针),那么它会在特定值处翻转。现在,我的问题是:回滚它指向的值是否有效(假设我在内存中有大量数据)?

我知道这是一个奇怪的问题,但我有一种情况是我不断地分配和释放内存。我发现在特定点,由于地址值无效,例如 ,0x20二进制崩溃。0x450x10101

我想知道问题是由于指针值的翻转,并且由于地址由于指针而翻转,因此它显示无效地址并在访问时崩溃。

我希望我所指的情况与所提出的问题相似。即使它们不同,我也想知道两者的答案。我尝试搜索“连续递增指针”,但没有找到答案。

编辑:这是在 Red Hat linux 上用 G++ 4.1.2 20080704 (Red Hat 4.1.2-48) 编译的新代码。

实际上,代码非常大,可以共享。但我可以用文字来概括:有 3 个线程:

  1. 第一个线程:它创建分配 Alert 类对象并将其推送到队列中。
  2. 第二个线程:它从队列中读取警报,处理它。
  3. 第三个线程:它在处理 20-30 分钟后释放分配给 Alert 对象的内存。

我已经验证了第三个线程在第二个线程处理之前没有释放它。

但是由于警报是定期生成的(即每秒大约数千个),所以我怀疑主要问题中提到的问题。在我的实现中需要注意的一点:我正在使用 linux 管道队列将它从一个线程推送到另一个线程。为此,我只从发送方推送对象的地址值,并确保不会在那里删除对象。这是一种可能的腐败方式吗?以下是此特定任务的代码:

Alert* l_alert = new Alert(ADD_ACTION,
                l_vehicleType,
                l_vehicleNo,
                l_projPolyline,
                l_speed,
                l_slotId);
    m_ResultHandler->SendToWorker(&l_alert);

队列功能的实现:

    S32 SendToWorker(queueDataType *p_instPtr)
    {
            S32 ret_val=SUCCESS;

            QueueObj.Lock();
            ret_val = QueueObj.Signal();
            QueueObj.push(*p_instPtr);
            QueueObj.UnLock();

            return ret_val;
    }

    S32 GetFromReceiver(queueDataType *p_instPtr)
    {
            QueueObj.Lock();
            while(QueueObj.size() == 0)
                    QueueObj.Wait();

            *p_instPtr = QueueObj.front();
            QueueObj.pop();
            QueueObj.UnLock();

            return SUCCESS;
    }

接收端:

m_alertQueue->GetFromReceiver(&l_alert)
4

2 回答 2

2

什么是操作系统?你在使用虚拟内存吗?C 标准允许指针指向数组末尾之后的一个地址(但不能取消引用)。

指向其他任何地方都是未定义的行为。

于 2013-09-09T10:42:46.497 回答
1

“near”和“far”指针的概念主要存在于 16 位模式下的 x86 编译器中,其中“near”指针是某种默认段的 16 位偏移量,而“far”指针是" 指针在指针本身有一个段和偏移值。在 32 位和 64 位操作系统中,指针(通常)只是平面内存模型中的偏移量(所有段都基于地址零)。

根据 C 标准,指针可以指向“单个对象或元素数组,以及一个过去的对象”。其他任何东西都是标准未定义的行为。这个声明的一个原因是支持分段内存,其中指针可能不容易在不同段之间进行比较(特别是如果段没有直接基地址,例如在 OS/2 1.x 中,使用 16 位保护模式,因此代码无法轻松访问段的基地址。由于段可以重叠,因此无法判断基地址 A + 偏移量 A 是否与基地址 B 相同或不同+ 偏移量 B)。

如果您有一个不满足此条件的指针,实际发生的情况是“未定义”。在 x86 环境中,真正的答案是“它不会崩溃,如果您读取内存也不会发生任何坏事”,但是当然,如​​果您尝试写入不属于“您的”的内存,那么坏事可能发生。确切的内容取决于您要覆盖的内存以及该内存的用途。如果不确切知道内存的用途以及写入的值是什么,就不可能准确地说出发生了什么。

在现代 32 位或 64 位操作系统中,访问“无效”内存肯定会导致程序崩溃,因为现代操作系统具有防止“野内存访问”的内存保护。

于 2013-09-09T10:57:38.987 回答