【问题标题】:Is there a way to limit data size at C++ compile time and produce a compile error?有没有办法在 C++ 编译时限制数据大小并产生编译错误?
【发布时间】:2019-03-30 10:12:06
【问题描述】:

我已经构建了一个工具,使学生能够在线(在受保护的环境中)编译和测试他们自己的 C++ 代码。

我想在编译时检查程序中的总数据量是否不超过一定大小,如果超过则产生编译错误。

(直接目标:限制 c++ std::array 大小)

我没有在网上找到信息。

我的编译链是:

g++ -Wall -Wextra -Waddress -std=c++11 -lm -fstack-protector -lm -o exename srcname

感谢您的帮助。

编辑 1

我给他们一个骨架,他们必须完成(此处)指定的位置:

“用‘produitTableau’的定义完成程序(这里),它得到一个整数和一个整数的二维数组,并将‘calcul’函数应用于它的每个值并返回修改后的数组。” (法语...)

#include <iostream>
#include <array>
using namespace std;

const int NB = 3;

int calcul (int a, int b);
array<array<int, NB>,NB> produitTableau(array<array<int, NB>,NB> t, int a);

int main()
{
    /* déclaration et initialisation  */
    array<array<int, NB>,NB> tab ;
    int x;
    cin >> x;
    for (int i=0;i<NB;i++) {for(int j=0; j<NB; j++) {cin >> tab[i][j];}}

    /* traitement et résultat  */
    tab = produitTableau(tab, x);

    /* résultat */
    for (int i=0; i < NB; i++) {
      for (int j=0; j < NB; j++) {
        cout << tab[i][j] << " ";
      }
    }

  return 0;
}

int calcul(int a, int b)
{
   return a*b;
}

**(here)**

我希望他们写出类似的东西(我使用存储在文本文件中并用作输入数据的测试数据集检查结果):

array<array<int, NB>,NB> produitTableau(array<array<int, NB>,NB> t, int a)
{
    for (int i=0; i < NB; i++) {
      for (int j=0; j < NB; j++) {
        t[i][j] = calcul(t[i][j] , a);
      }
    }

   return t;

}

* 数组是按值传递的 *

所以我会检查使用的数据总量是否超过某个值,例如:10.000 字节。

可能是exe文件...我不知道。

【问题讨论】:

  • 但是您到底想限制什么样的数据?取决于提到的std::array 的使用方式,它会落在.bss、堆栈或堆中 - 取决于您的学生决定如何使用它。您必须限制所有这些(以及可能的 .data)。
  • 你必须比这更具体一点,看起来你在一些细节上有点糊涂;你到底想用你的限制来实现什么?这可能是 X/Y 情况(即您可能在这里尝试解决错误的问题)
  • 你能限制受保护环境的内存吗?
  • “受保护的环境”不是正确的术语:它受到保护,因为学生需要一个 ID 和密码......
  • 我找到了一个编译选项,如果对象的 siez 大于 x 时会发出警告:“...警告:'t2' 的大小为 4000000 字节 [-Wlarger-than=] |”。这可能是解决方案。但是把警告变成错误?但这不是使用的数组总数...

标签: c++ c++11


【解决方案1】:

好吧,如果您阻止包含其他任何内容,您可以调整 std::array&lt;T, N&gt; 以便将 N 限制为某个最大大小;然后让学生包含该数组。

适应可能就像添加一样简单:

static_assert(N == NB, "For this homework assignment you can only use arrays of NB elements");

在数组类中,在文件的前面,

constexpr const size_t NB = 123;

当然切记不要更改原始数组文件!制作一个副本(甚至可以更改名称以说明它是一个自定义数组)。

【讨论】:

  • 这可能是一个解决方案:每个作业都需要一个班级。但是多维数组(例如矩阵)呢?
  • @PatrickDezecache:那会有所不同。但请记住,标准库没有矩阵/张量容器。
  • 作为矩阵,我的意思是二维数组,每个维度都有自己的值,并不总是方阵。
  • @PatrickDezecache:是的,我意识到这一点,但这与您提出的问题不同。一般来说,我会说 - 选择你喜欢的矩阵的任何实现,制作一个副本,并限制它的尺寸 - 无论是静态的还是动态的。
【解决方案2】:

我将实施到部分:

  1. 检查源源固定的约束
  2. 使用编译器选项检查大小限制

# 1. 检查源源固定的约束 #

来自@einpoklum 的建议,

## 1.1 将“array”头文件复制到“myArray”并添加“assert”##

...
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

template<typename _Tp, std::size_t _Nm>
    struct array
    {
       typedef _Tp                        value_type;
      ...
       typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;

       // Support for zero-sized arrays mandatory.
       value_type _M_instance[_Nm ? _Nm : 1];

       static_assert(_Nm == NB, "Check array size...");  <<<<<<<<<<<<

  ... continue...

## 1.2 在主程序中定义数组大小##

const unsigned int NB = 10;  <<<<<<<<<<<<<<<<<<<<<<<<w
#include <iostream>
#include "myArray.h" <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
...

示例 1:

const unsigned int NB = 10;
...
#include "myArray.h"
...
int main()
{
    array<int, 11> tab;
    ...
}

在编译时:错误:静态断言失败:检查数组大小...

# 2. 使用编译器选项检查大小限制 #

使用编译器选项来强制控制(限制误用的风险:例如 C 数组,或数组的多重定义,...

g++ 编译器选项:

  1. -Wlarger-than=x : 检查对象的大小(以字节为单位)

  2. -Wframe-larger-than=x : 检查函数的大小 [https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options][1] -Wframe-larger-than=byte-size

  3. -Werror : 将警告转为错误

示例 1:(-Wlarger-than=10000)

const int NB = 100;
...
array<array<int, NB>,NB> tab ;

产生错误:...错误:'tab' 的大小为 40000 字节 [-Werror=larger-than=]|

示例 2:(简化示例)(-Wframe-larger-than=10000)

int main()
{
    array<array<int, 100>,100> tab ;
    int x;
    ...
    tab = produitTableau(tab, x);

    return 0;
}

array<array<int, 100>,100> produitTableau(array<array<int, 100>,100> t, int a)
{
...
   return t;
}

产生错误:...错误:80016 字节的帧大小大于 10000 字节 [-Werror=frame-larger-than=]|

80016 字节 = 制表符 10000*4=40000 字节 + 按值传递的参数 = 40000 字节 + 其他变量...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    相关资源
    最近更新 更多