You need to enable JavaScript to run this app. 如何提升C++课程自动评分器可靠性,防止学生提交代码作弊
优惠活动
大模型
产品
解决方案
定价
更多

如何提升C++课程自动评分器可靠性,防止学生提交代码作弊

提升自动评分器可靠性的低成本方案

以下方法无需大幅改动现有Docker、编译脚本流程,落地成本极低,可覆盖绝大多数常见作弊场景:

  • 隔离标准输出流,切断学生伪造成绩的通道
    这是最立竿见影的实现:在你提供的主程序最开头,提前把真正关联系统标准输出的流对象保存下来,再把全局std::cout重定向到内存缓冲区。示例代码:
    // 主程序入口第一行执行
    #include <sstream>
    // 保存真正绑定系统stdout的流,只有评分逻辑能用这个对象输出
    std::ostream& real_stdout = std::cout.rdbuf();
    // 把全局cout重定向到内存空缓冲区:学生代码不管往cout打什么,都会被存在内存里,根本碰不到真正的系统输出
    std::ostringstream student_output_holder;
    std::cout.rdbuf(student_output_holder.rdbuf());
    
    // ... 原有的test逻辑、grade计算逻辑全部正常编写
    // 最后输出成绩时,必须用提前保存的real_stdout,不能直接用std::cout
    real_stdout << "Grade: " << grade << std::endl;
    
    这种方式下,哪怕学生在func里直接写std::cout << "Grade: 100"; exit(0);,打印的内容只会被存到内存缓冲区,根本不会传到容器的真实标准输出;如果学生直接调用exit提前终止程序,主程序的成绩输出语句根本不会执行,评分脚本读不到任何成绩行,会直接判0分,完全拿不到伪造的满分。
  • 给成绩输出加动态随机校验标记
    每次批量编译作业的时候,由脚本生成一个6-8位的无规律随机字符串,作为宏传入主程序,让评分器输出的成绩行必须带这个串。示例流程:
    1. bash脚本编译时生成随机串:SECRET=$(head -c 8 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')
    2. 编译时把这个串作为宏传给主程序:g++ -DGRADE_SECRET=\"$SECRET\" main.cpp func.cpp -o grader
    3. 主程序输出成绩时带上这个串:real_stdout << GRADE_SECRET << " Grade: " << grade << std::endl;
    4. 评分脚本抓最后一行输出时,必须匹配到这个提前生成的随机串才算有效输出,否则直接判无效。
      这个随机串每次编译都会变,学生根本没法提前知道值是什么,哪怕想办法绕过了输出重定向,伪造出来的成绩行没有这个随机标记,也通不过校验。
  • 编译阶段拦截越权操作
    在bash编译流程里加两个简单检查,几乎零成本:
    • 检查学生提交的代码里有没有自定义main函数:如果学生提交的目标文件符号表里出现main符号,直接中断编译,不让学生有机会绕过你写的测试流程跑自己的伪造程序。
    • 链接阶段用--wrap参数把学生代码对exit、system等可以直接终止流程、执行外部命令的函数的调用,替换成空的占位实现。学生哪怕想调用exit直接退程序拿成绩,也根本无法触发程序终止。
  • 收紧Docker运行的权限边界
    你现在已经用Docker做隔离了,只要启动容器的时候加两个简单参数:把容器的标准输出通过只读管道传给评分脚本,不允许学生进程直接写入管道的写端,从系统层面堵死学生代码直接往评分脚本读的通道写内容的可能。

内容的提问来源于stack exchange,提问作者Erel Segal-Halevi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.31 12:24:04