如果我们在C中连续递增指针,指针会指向错误的地址吗?

时间:2013-09-09 10:32:56

标签: c++ pointers memory

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

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

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

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

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

实际上代码非常大,无法分享。但我可以用文字说明: 有3个主题:

  1. 第一个线程:它创建分配Alert类对象并将其推入队列。
  2. 第二个线程:它从队列中读取Alert,处理它。
  3. 第三个线程:在处理20-30分钟后释放分配给Alert对象的内存。
  4. 我已经验证第三个线程在第二个线程处理之前没有解除分配。

    但由于警报是定期生成的(即一秒钟左右),所以我怀疑主要问题中提到的问题。 我的实施中要注意的要点: 我正在使用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)
    

2 个答案:

答案 0 :(得分:2)

什么是操作系统?你在使用虚拟内存吗?允许指针指向超过数组末尾的一个地址(但未解除引用)的C标准says

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

答案 1 :(得分:1)

概念“near”和“far”指针是一个概念,主要存在于16位模式下x86的编译器中,其中“near”指针是某种默认段的16位偏移量,并且“far”指针在指针本身中有一个段和偏移值。在32位和64位OS中,指针(通常)只是平坦存储器模型中的偏移(所有段都基于地址0)。

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

如果您的指针不符合此条件,实际上会发生“未定义”。在x86环境中,真正的答案是“它不会崩溃,如果你读取内存就不会发生任何坏事”,但当然,如果你试着写入不是“你的”的内存,那么坏可能发生。究竟是什么取决于你覆盖的内存,以及该内存的用途。如果不确切知道内存的用途以及写入内存的值,就​​不可能确切地说出会发生什么。

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