C++ 超出限制访问阵列

C++ 超出限制访问阵列,c++,arrays,C++,Arrays,我有两个大小为100的字符数组char array1[100],char array2[100]。现在我只想检查是否有人访问数组超过了限制。这是必要的,因为假设为array1和array2分配的内存是连续的,array1完成后array2开始。现在,如果有人写:array1[101],概念上是错误的,但编译器会给出警告,但不会崩溃。那么,我怎样才能发现并解决这些问题呢 更新1: 我已经有15000行的代码了。对于这些代码,我必须检查这个条件,我可以调用我的函数,但不能更改编写的代码。请根据这一点

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

更新1:


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

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

编辑:
这当然是一种运行时预防。不知道如果编译器不能为您检查,您将如何在编译时检查它。另外,正如Kolky已经指出的,如果我们知道您使用的是哪种语言,那么回答这个问题就更容易了。

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

编辑:
这当然是一种运行时预防。不知道如果编译器不能为您检查,您将如何在编译时检查它。另外,正如Kolky已经指出的,如果我们知道您使用的是哪种语言,那么回答这个问题就更容易了。

大多数现代语言都会检测到这一点并防止它发生。C和它的衍生物没有检测到这一点,基本上也无法检测到这一点,因为可以通过多种方式访问内存,包括裸指针。如果您可以限制访问内存的方式,那么您可以使用函数或其他方法来检查您的访问。

大多数现代语言都会检测到这一点并防止其发生。C和它的衍生物没有检测到这一点,基本上也无法检测到这一点,因为可以通过多种方式访问内存,包括裸指针。如果您可以限制访问内存的方式,那么您可以使用函数或其他东西来检查您的访问。

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

char * ptr = &array2;
ptr = foo(ptr); // ptr --;
ptr现在包含一个有效地址,但该地址在array2之外。这可能是一个bug,也可能是您想要的。C不知道在C中没有办法说我想要它,所以编译器无法检查它。愚蠢地:

char*array2=malloc100

C编译器如何知道您正在将内存作为字符数组处理,并且在编写&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个字节是否未被触及,即mungwall模式是否仍然完好无损。虽然不是完美的,但它会让你的程序更早崩溃,希望更接近bug

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

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

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


语言不会老化。C现在已经40岁了,我们的知识也在进步。它仍然在很多地方使用,但它不应该再成为首选。同样的情况也适用于C++的扩展,因为它受到C的基本缺陷,即使现在有许多围绕它们的库和框架。C++中的

< P>,没有一般的解决方案。您不能在编译时这样做,因为在C中更改内存的方法太多了。例如:

char * ptr = &array2;
ptr = foo(ptr); // ptr --;
ptr现在包含一个有效地址,但该地址在array2之外。这可能是一个bug,也可能是您想要的。C不知道在C中没有办法说我想要它,所以编译器无法检查它。愚蠢地:

char*array2=malloc100

C编译器如何知道您正在将内存作为字符数组处理,并且在编写&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;
}
在空闲状态下,它将检查分配内存a前后的16个字节 rea未被触碰,即mungwall图案仍然完好无损。虽然不是完美的,但它会让你的程序更早崩溃,希望更接近bug

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

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

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


语言不会老化。C现在已经40岁了,我们的知识也在进步。它仍然在很多地方使用,但它不应该再成为首选。同样的情况也适用于C++,因为它有C的基本缺陷,即使现在有许多在它们周围工作的库和框架。

< P>如果你使用C++而不是C,你有什么理由不能使用STD::vector?如果用户超出了您的范围,那么您将进行边界检查。我是不是遗漏了什么


防止用户首先访问集合是否明智?

< P>如果你使用C++而不是C,你有什么理由不能使用STD::vector?如果用户超出了您的范围,那么您将进行边界检查。我是不是遗漏了什么


防止用户在第一次直接访问集合不是明智的吗?

< P>如果你在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

问题已解决,但如果通过指针衰减进行访问,则不会进行边界检查。你可以使用Booo::数组预提供的解决方案。

< P>如果你在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预先提供的解决方案。

如果您对代码运行静态分析器,即cppcheck,则会出现边界错误


要解决它。。。最好使用某种容器,如std::vector或编写包装器,如果对代码运行静态分析器,如cppcheck,则会出现边界错误


要解决它。。。最好使用某种容器,如std::vector或编写包装器如果使用boost::array或类似工具,如果超出数组边界,将出现异常范围错误。Boost非常棒。

如果使用Boost::array或类似工具,如果超出数组边界,则会出现异常范围错误。Boost是非常棒的。< / P>这取决于C++语言的使用。我使用C++语言。这取决于你使用的语言…我用C++语言。在C++中,写一个简单的包是很容易的。声明C++中没有通用解决方案是错误的。我说有很多框架在它们周围工作。但是很多哑C代码都用C++编译,用错误的参数调用错误函数,你就可以感觉到建立一个卡房子。在C++中,写一个简单的包是很容易的。声明C++中没有通用解决方案是错误的。我说有很多框架在它们周围工作。但是很多哑C代码都是用C++编译的,如果用错误的参数调用错误函数,你就可以感觉到建立一个卡房子。为什么要重新发明轮子?这个问题的现有解决方案已经过验证,可以保存OP测试他/她自己的版本。此外,我会制作索引和类型大小,这样就不必与0.Meh进行比较。它不应该是理想主义的完美工作代码,而是一个起点。为什么要重新发明轮子?这个问题的现有解决方案已经过验证,可以保存OP测试他/她自己的版本。此外,我会制作索引和类型大小,这样就不必与0.Meh进行比较。它不应该是理想主义的完美工作代码,而是一个起点。