据我所知,C / C ++中的近指针(或非指针)的地址值比RAM中的实际地址小。因此,如果我继续递增指针(比如int类型或任何对象类型指针),那么在特定值处它将翻转。现在,我的问题是:回滚它指向的值是否有效(假设,我在内存中有大量数据)?
我知道这是一个奇怪的问题,但我有一种情况,我不断分配和释放内存。我发现在特定点上二进制崩溃是由于无效的地址值造成的
0x20
,0x45
或0x10101
等。
我想知道问题是由于指针值的翻转而导致地址因指针而翻转,因此它显示无效地址并在访问时崩溃。
我希望我提到的情况类似于被问到的问题。即使它们不同,我也想知道两者的答案。我尝试搜索“连续递增指针”,但没有找到我的答案。
编辑:这是在Red Hat linux上用G ++ 4.1.2 20080704(Red Hat 4.1.2-48)编译的新代码。
实际上代码非常大,无法分享。但我可以用文字说明: 有3个主题:
我已经验证第三个线程在第二个线程处理之前没有解除分配。
但由于警报是定期生成的(即一秒钟左右),所以我怀疑主要问题中提到的问题。 我的实施中要注意的要点: 我正在使用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)
答案 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位操作系统中,访问“无效”的内存肯定会导致程序崩溃,因为现代操作系统具有防止“疯狂内存访问”的内存保护。