此代码是否会抛出访问冲突异常

时间:2017-01-11 12:55:58

标签: c++ templates pointers

考虑以下代码:

template <typename T>
void foo(unsigned char * tempbuf, T val, int &nMatches, int nSize)
{
    T temp_val;
    for (int offset = 0; offset < nSize; ++offset)
    {
        temp_val = *((T*)&tempbuf[offset]);
        if (temp_val == val)
        {
            ++nMatches;
        }               
    }
}
int main ()
{
    int nValue = 5;
    int nMatches(0);
    const int size = 1000;
    unsigned char *buffer = reinterpret_cast <unsigned char *>(malloc(size));
    foo(buffer, nValue, nMatches, size);
    return 1;
}

考虑到nValue是一个int,foo将读取缓冲区的第1000个字节作为int(例如,至少32位变量)。这是否意味着由于非分配内存上的访问冲突而可能抛出异常? (假设int是4个字节,最后一次读取可能不存在3个字节,如果它们确实存在则可能有垃圾值,所以我知道它至少是UB,但考虑到要读取的地址本身是有效的我不确定异常)。

1 个答案:

答案 0 :(得分:2)

假设如下:

  • 你知道,在分配缓冲区之外阅读是一种可怕的做法
  • 我们不是在谈论“如何修复代码”,而只是关于“可能发生的事情”

正如您所提到的,在foo()内循环的最后一次迭代中,您正在读取分配缓冲区之外的几个字节。访问随机存储器总是有可能与segmentation fault崩溃,但在这种特殊情况下,不良结果的可能性微不足道,但仍然不为零。原因:

  • 缓冲区在堆内分配,因此缓冲区之后的字节也可能是堆的一部分(除非缓冲区正好位于堆边框上),因此读取将返回垃圾而没有失败。
  • 即使走出堆外也许不会打你。几乎不可能预测,你会阅读什么记忆,尤其是address randomization technique。你有机会获得好的和坏的结果(例如地址空间边界上的堆肯定会导致读取错误)。根据谷歌的说法,通过试验VMMap实用程序可以获得有关虚拟内存映射的深刻见解,但我并没有为自己做这些。

所以最重要的是你的程序里面有炸弹炸弹,但目前还不清楚我们是否会看到爆炸。