You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Docker的C代码在线判题环境运行时错误无法检测的问题求助

问题分析与解决方案

你的问题主要来自三个核心问题:set -e的干扰、命令组合与重定向的逻辑错误,以及指标文件的覆盖问题。下面逐一拆解并给出修复方案:

1. 移除set -e,避免脚本提前退出

set -e会让脚本在任何命令返回非零值时立即终止,这意味着当你的C程序触发运行时错误时,timeout/time命令返回的非零退出码会直接让脚本退出,根本无法执行后续的退出码捕获和状态判断逻辑。

由于你已经在编译阶段手动处理了退出码,set -e完全是多余的,反而会破坏运行时错误的检测流程。

2. 调整命令组合与重定向,正确捕获错误信息和退出码

原来的命令没有正确区分/usr/bin/time的输出和程序自身的错误信息,导致运行时错误的提示(比如Floating point exception)无法被写入error.txt,同时time的退出码传递也出现了问题。

正确的做法是用bash -c包裹程序的运行命令,单独处理程序的输入输出重定向,让/usr/bin/time只负责收集内存指标:

timeout 10 /usr/bin/time -f "MEM:%M" -o /code/metrics.txt bash -c '/code/a.out < /code/input.txt > /code/output.txt 2> /code/error.txt'

这样,程序的标准输出写入output.txt,程序的标准错误和崩溃提示写入error.txt,time的内存统计写入metrics.txt,同时timeout会正确传递程序的退出码。

3. 修复metrics.txt的覆盖问题

你原来的脚本中,运行完time后用echo "TIME:$elapsed_time" > /code/metrics.txt会覆盖time写入的内存信息,应该改用追加模式>>:

echo "TIME:$elapsed_time" >> /code/metrics.txt

修改后的完整run_c_code.sh脚本

#!/bin/bash
# 移除set -e,避免提前退出

gcc /code/main.c -o /code/a.out 2> /code/compile_error.txt
compile_exit=$?
if [ $compile_exit -ne 0 ]; then
    echo "COMPILE_ERROR" > /code/status.txt
    exit $compile_exit
fi

# 如果编译完成但compile_error.txt非空,判定为警告
if [ -s /code/compile_error.txt ]; then
    echo "COMPILE_WARNING" > /code/status.txt
fi

# 运行代码
start_time=$(date +%s%N)
timeout 10 /usr/bin/time -f "MEM:%M" -o /code/metrics.txt bash -c '/code/a.out < /code/input.txt > /code/output.txt 2> /code/error.txt'
exit_code=$?
echo "E_CODE=$exit_code" > /code/status_code.txt
end_time=$(date +%s%N)
elapsed_time=$(( (end_time-start_time) / 1000000))
echo "TIME:$elapsed_time" >> /code/metrics.txt  # 改为追加模式

if [ $exit_code -eq 124 ]; then
    echo "TIMEOUT" > /code/status.txt
    exit 124
elif [ $exit_code -ne 0 ]; then
    echo "RUNTIME_ERROR" > /code/status.txt
    exit $exit_code
else
    echo "SUCCESS" > /code/status.txt
fi

额外优化点

  • 将if [ -f /code/compile_error.txt ]改为if [ -s /code/compile_error.txt ]:检查文件是否非空,避免gcc输出空内容(无警告无错误)时误判为编译警告。
  • 保留USER runner的设置:沙箱环境使用非root用户运行代码是正确的安全实践,无需修改。

测试验证

重新构建Docker镜像后运行你的Python测试代码,现在应该能得到预期结果:

  • exit_code为136(对应除零错误的SIGFPE信号)
  • error.txt包含Floating point exception的错误信息
  • status.txt显示RUNTIME_ERROR
  • Python中的result.returncode为136

内容的提问来源于stack exchange,提问作者Papazy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 12:47:27