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

Ubuntu下如何为GCC编译的C代码添加超时看门狗检测死循环?

给运行C程序的Python脚本添加看门狗超时机制

绝对没问题!既然不能修改C代码,咱们完全可以在Python层面给每个运行的C程序实例加上“超时看门狗”,一旦运行超过X分钟就判定为死循环(或长时间无响应)并给出提示。下面给你两种实用的实现方案:

方案一:用subprocess内置的超时参数(简单直接)

Python的subprocess模块自带timeout参数,能直接限制子进程的运行时间,超出后会抛出TimeoutExpired异常,咱们捕获这个异常就能判断程序可能陷入死循环了。

示例代码

import subprocess
import os

def run_c_program(c_source_path, input_file_path, timeout_minutes=5):
    # 先编译C代码(假设你的C程序读取标准输入)
    exe_path = c_source_path.replace(".c", ".out")
    compile_cmd = ["gcc", c_source_path, "-o", exe_path]
    try:
        subprocess.run(compile_cmd, check=True, capture_output=True, text=True)
    except subprocess.CalledProcessError as e:
        print(f"编译失败:{e.stderr}")
        return

    # 读取输入文件内容,传给C程序的标准输入
    with open(input_file_path, "r") as f:
        input_data = f.read()

    # 运行C程序,设置超时时间(转换为秒)
    timeout_seconds = timeout_minutes * 60
    try:
        result = subprocess.run(
            [exe_path],
            input=input_data,
            capture_output=True,
            text=True,
            timeout=timeout_seconds
        )
        # 程序正常结束的处理逻辑
        print(f"程序运行完成,返回码:{result.returncode}")
        # 可以在这里处理输出、日志等
    except subprocess.TimeoutExpired:
        print(f"警告:程序运行超过{timeout_minutes}分钟,疑似陷入死循环!")
        # 可以强制终止子进程(不过subprocess超时后会自动终止)
    finally:
        # 清理编译后的可执行文件(可选)
        if os.path.exists(exe_path):
            os.remove(exe_path)

# 调用示例:运行test.c,用input.txt作为输入,超时设为3分钟
run_c_program("test.c", "input.txt", timeout_minutes=3)

说明

  • 这个方案的优势是代码简洁,无需额外依赖,适合大多数基础场景。
  • subprocess.TimeoutExpired触发时,Python会自动终止对应的C程序进程,不用担心残留进程。
  • 如果你的C程序是通过命令行参数接收输入而非标准输入,只需要调整subprocess.run的参数列表即可。

方案二:用psutil实现更灵活的监控(含内存监控)

如果除了超时,你还想监控C程序的内存占用(毕竟你提到通过内存耗尽发现死循环),可以用psutil模块,它能实时跟踪进程的运行时间、内存、CPU使用率等指标,实现更精细化的看门狗。

步骤1:安装依赖

pip install psutil

示例代码

import subprocess
import os
import time
import psutil

def monitor_c_program(c_source_path, input_file_path, timeout_minutes=5, max_memory_mb=500):
    # 编译C代码
    exe_path = c_source_path.replace(".c", ".out")
    compile_cmd = ["gcc", c_source_path, "-o", exe_path]
    try:
        subprocess.run(compile_cmd, check=True, capture_output=True, text=True)
    except subprocess.CalledProcessError as e:
        print(f"编译失败:{e.stderr}")
        return

    # 启动C程序,不阻塞,让它后台运行
    with open(input_file_path, "r") as f:
        input_data = f.read()
    proc = subprocess.Popen(
        [exe_path],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True
    )
    proc.stdin.write(input_data)
    proc.stdin.close()

    # 开始监控
    start_time = time.time()
    timeout_seconds = timeout_minutes * 60
    is_timeout = False
    is_memory_exceeded = False

    while proc.poll() is None:  # 进程还在运行
        elapsed_time = time.time() - start_time
        # 检查超时
        if elapsed_time > timeout_seconds:
            is_timeout = True
            break
        # 检查内存占用
        try:
            process = psutil.Process(proc.pid)
            memory_info = process.memory_info()
            memory_used_mb = memory_info.rss / (1024 * 1024)  # 转换为MB
            if memory_used_mb > max_memory_mb:
                is_memory_exceeded = True
                break
        except psutil.NoSuchProcess:
            # 进程已经意外终止
            break
        # 每隔10秒检查一次,避免占用过多CPU
        time.sleep(10)

    # 根据监控结果处理
    if is_timeout:
        print(f"警告:程序运行超过{timeout_minutes}分钟,疑似陷入死循环!")
    elif is_memory_exceeded:
        print(f"警告:程序内存占用超过{max_memory_mb}MB,疑似内存泄漏/死循环!")
    else:
        # 程序正常结束,处理输出
        stdout, stderr = proc.communicate()
        print(f"程序运行完成,返回码:{proc.returncode}")
        if stdout:
            print(f"标准输出:{stdout}")
        if stderr:
            print(f"标准错误:{stderr}")

    # 确保进程被终止
    if proc.poll() is None:
        proc.kill()
        proc.wait()

    # 清理可执行文件
    if os.path.exists(exe_path):
        os.remove(exe_path)

# 调用示例:超时5分钟,内存上限500MB
monitor_c_program("test.c", "input.txt", timeout_minutes=5, max_memory_mb=500)

说明

  • 这个方案不仅能监控超时,还能跟踪内存占用,完美匹配你提到的“内存耗尽”死循环场景。
  • 通过psutil.Process可以获取进程的更多指标,比如CPU使用率,你可以根据需求添加更多监控条件。
  • 循环中加入time.sleep(10)是为了避免Python进程频繁检查,节省系统资源,你可以根据需要调整间隔时间。

两种方案都不需要修改任何C代码,完全在Python层面实现看门狗逻辑,你可以根据自己的需求选择合适的一种。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:54:06