有没有办法在 C++ 编译时限制数据大小并产生编译错误?
Posted
技术标签:
【中文标题】有没有办法在 C++ 编译时限制数据大小并产生编译错误?【英文标题】:Is there a way to limit data size at C++ compile time and produce a compile error? 【发布时间】: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=] |”。这可能是解决方案。但是把警告变成错误?但这不是使用的数组总数...
【参考方案1】:
好吧,如果您阻止包含其他任何内容,您可以调整 std::array<T, N>
以便将 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. 检查源源固定的约束 #
来自@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++ 编译器选项:
-Wlarger-than=x : 检查对象的大小(以字节为单位)
-Wframe-larger-than=x : 检查函数的大小 [https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options][1] -Wframe-larger-than=byte-size
-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 字节 + 其他变量...
【讨论】:
以上是关于有没有办法在 C++ 编译时限制数据大小并产生编译错误?的主要内容,如果未能解决你的问题,请参考以下文章