在C或C ++中检查边界是否昂贵?

时间:2014-06-19 17:16:48

标签: c++ c

  

绑定检查很昂贵   (>运行时开销的x2倍)

我从我的一位教授那里得到了这一点。我很困惑。 据我所知,程序中最耗时的部分是IO(来自网络和硬盘)。

但是用C或C ++检查边界并不总是与这两个输入源相关。 例如,我使用memcpy(dest, src, length(src))在C中将一个buff的内容复制到另一个buff。在此之前,我检查src的大小,以防止堆溢出。我可以成像的进动是:获取src的起始地址和\x00中的src字节(在汇编语言的视图中,我复制了src的内容逐个查看该字节是否与\x00等效。获取2地址后,只需将它们减去以获得src的长度。我从内存中读到了src的内容。我们都知道从记忆中读取东西很快。

2 个答案:

答案 0 :(得分:10)

我刚刚运行了一个程序,启用了迭代器边界检查。

运行时间从789毫秒增加到2608毫秒。

是的,这很重要。不是所有的时间,但肯定比从来没有。

特别是,绑定检查的迭代器需要至少两倍于简单指针的存储空间,而且,不容易优化。从理论上讲,它们简单而有效,但在实践中,你根本就不想做你不需要做的工作。

哦,我是否提到编译的时间也从7.72秒增加到13.21秒?


对于你们中间的许多非信徒......一个微型例子需要0.92 seconds without bounds checking1.96 seconds with


由于对所有的怀疑很多,包括vector的效率......这里是另一个:

#include <cstdio>
#include <ctime>

template<class T> struct Vector
{
    T *b, *e;
    Vector(size_t n) : b(new T[n]), e(b + n) { }
    T &operator[](size_t i) { return b[i]; }
    T &at(size_t i) { if (i >= e - b) { throw "invalid"; } return b[i]; }
};

#define at operator[]  // Comment this out to enable bounds-checking

int main(int argc, char **argv)
{
    Vector<size_t> v(1 << 16);
    for (size_t *p = v.b; p != v.e; ++p) { *p = 1; }
    clock_t begin = clock();
    for (int j = 0; j < 1 << 12; ++j)
    {
        for (size_t i = 8, n = v.e - v.b; i < n; ++i)
        {
            v.at(i) += v.at(i - 8);
            v.at(i) ^= v.at(i - 7);
            v.at(i) -= v.at(i - 6);
            v.at(i) ^= v.at(i - 5);
            v.at(i) += v.at(i - 4);
            v.at(i) ^= v.at(i - 3);
            v.at(i) -= v.at(i - 2);
            v.at(i) ^= v.at(i - 1);
        }
    }
    clock_t end = clock();
    fprintf(stderr, "%u\n", clock() - begin);
}

2.09 seconds0.88 seconds

答案 1 :(得分:2)

直到20世纪80年代,这一直是真实的。

通过现代代码生成和高度流水线化的CPU架构,可以在零或非常少的额外执行成本的情况下完成边界检查。这是因为边界检查可以与内存提取同时进行。