访问超出限制的数组

时间:2010-09-07 11:51:50

标签: c++ arrays

我有两个大小为100的字符数组(char array1 [100],char array2 [100])。现在我只想检查是否有人访问超出限制的数组。这是必要的,因为假设为array1和array2分配的内存是连续的意思,因为array1完成然后array2启动。现在,如果有人写:array1 [101],概念上它错了,但编译器会发出警告,但不会崩溃。那么我怎样才能发现这个问题并解决它?

更新1:

我已经拥有15,000行的代码。对于该代码,我必须检查这个条件,我可以调用我的函数,但不能更改编写的代码。请根据这个建议我。

7 个答案:

答案 0 :(得分:2)

我对此的初始响应是在函数或方法中包含对这些数组的访问,并将索引作为参数发送。如果索引超出范围,则引发异常或以其他方式报告错误。

修改 这当然是运行时预防。如果编译器无法为您检查,那么不知道如何在编译时检查它。此外,正如Kolky已经指出的那样,如果我们知道您正在使用哪种语言,那么回答这个问题会更容易。

答案 1 :(得分:2)

大多数现代语言都会检测到这种情况并防止它发生。 C及其衍生物不会检测到这一点,并且基本上无法检测到这一点,因为您可以通过多种方式访问​​内存,包括裸指针。如果您可以限制访问内存的方式,那么您可以使用某个功能或其他内容来检查您的访问权限。

答案 2 :(得分:1)

如果您使用的是C ++而不是C,那么您有什么理由不能使用std :: vector吗?这将为您提供检查用户是否超出您的范围的界限。我在这里错过了什么吗?

首先阻止用户直接访问集合是不明智的?

答案 3 :(得分:1)

如果使用boost :: array或类似的话,如果超出数组边界,则会得到异常range_error。 http://www.boost.org/doc/libs/1_44_0/doc/html/boost/array.html。提升很棒。

答案 4 :(得分:0)

如果您使用的是C ++,则可以编写快速包装类。

template<typename T, int size> class my_array_wrapper {
    T contents[size];
public:
    T& operator[](int index) {
        if (index >= size)
            throw std::runtime_error("Attempted to access outside array bounds!");
        if (index < 0)
            throw std::runtime_error("Attempted to access outside array bounds!");
        return contents[index];
    }
    const T& operator[](int index) const {
        if (index >= size)
            throw std::runtime_error("Attempted to access outside array bounds!");
        if (index < 0)
            throw std::runtime_error("Attempted to access outside array bounds!");
        return contents[index];
    }
    operator T*() {
        return contents;
    }
    operator const T*() const {
        return contents;
    }
};

my_array_wrapper<char, 100> array1;
array1[101]; // exception

问题解决了,虽然如果你通过指针衰减访问,将没有边界检查。您可以使用boost :: array预先提供的解决方案。

答案 5 :(得分:0)

如果你对你的代码运行静态分析器(即cppcheck),它会给你一个边界错误 http://en.wikipedia.org/wiki/User:Exuwon/Cppcheck#Bounds_checking

解决它...你最好使用某种容器(即std :: vector)或编写包装器

答案 6 :(得分:-1)

在C / C ++中,没有通用的解决方案。你不能在编译时这样做,因为有太多的方法来改变C中的内存。例如:

char * ptr = &array2;
ptr = foo(ptr); // ptr --;

ptr现在包含有效地址,但地址超出array2。这可能是一个错误或你想要的。 C无法知道(在C中没有办法说“我想要它”),所以编译器无法检查它。 Sililarily:

char * array2 = malloc(100);

C编译器应该如何知道您将内存视为char数组,并且在编写&array2[100]时会发出警告?

因此,大多数解决方案使用“mungwalls”,即当您调用malloc()时,它们实际上会比您要求的分配16/32字节:

malloc(size) {
    mungwall_size = 16;
     ptr = real_malloc(size + mungwall_size*2);
     createMungwall(ptr, mungwall_size);
     createMungwall(ptr+size, mungwall_size);
     return ptr+size;
}

free()中,它将检查未分配的内存区域之前和之后的16个字节(即,绿墙模式仍然完好无损)。虽然不完美,但它会使您的程序更早崩溃(并希望更接近错误)。

您还可以使用特殊的CPU命令来检查所有内存访问,但这种方法会使您的程序比现在慢100到100万倍。

因此,C之后的语言不允许指针,这意味着“数组”是具有大小的基本类型。现在,您可以通过简单的比较检查每个阵列访问。

如果你想用C语言编写保存的代码,你必须模仿它。创建一个数组类型,永远不要使用指针或char *表示字符串。这意味着您必须始终转换数据类型(因为所有库函数都使用const char *作为字符串)但它会使您的代码更安全。

语言会老化。 C现在已有40年历史,我们的知识已经发展。它仍然在很多地方使用,但它不应该是第一选择。这同样适用于(在较小的范围内)C ++,因为它遭受了与C相同的基本缺陷(即使您现在拥有可以解决其中许多问题的库和框架)。