找 C 片段里的漏放

👁️ 4 人浏览 💬 0 人评论 ❤️ 添加收藏

本节的东西:

TABLE   三语言对照:(声明, 拿, 放, 自动放)
count_pairs(src)   C 源码里 pthread_mutex_lock / unlock 各几次
find_leak(src)   按行扫 C:拿了锁之后、放锁之前遇到 return 的行号
guard_span(src)   C++:lock_guard 声明的那一行到它所在花括号块结束的那一行

贯穿 n07 的 C 片段(C_SRC):

int take(int k) {
  pthread_mutex_lock(&m);
  if (stock < k) return -1;
  stock -= k;
  pthread_mutex_unlock(&m);
  return stock;
}

void put(int k) {
  pthread_mutex_lock(&m);
  stock += k;
  pthread_mutex_unlock(&m);
}

按行扫,找拿了锁之后、放锁之前就 return 的行:

TABLE = {
    "python3": ("threading.Lock()", "lock.acquire()", "lock.release()", "with lock:"),
    "c": ("pthread_mutex_t m", "pthread_mutex_lock(&m)", "pthread_mutex_unlock(&m)", "(没有:只能手动配对)"),
    "cpp": ("std::mutex m", "m.lock()", "m.unlock()", "std::lock_guard<std::mutex> g(m)"),
}


def count_pairs(src):
    """C 源码里 lock 和 unlock 各出现几次。"""
    return src.count("pthread_mutex_lock("), src.count("pthread_mutex_unlock(")


def find_leak(src):
    """按行扫 C 源码:拿了锁之后、放锁之前遇到 return,就是一条泄漏;交回泄漏所在的行号列表(从 1 起)。"""
    held = False
    leaks = []
    for i, line in enumerate(src.split("\n"), 1):
        s = line.strip()
        if "pthread_mutex_lock(" in s:
            held = True
        elif "pthread_mutex_unlock(" in s:
            held = False
        elif "return" in s and held:
            leaks.append(i)
    return leaks


def guard_span(src):
    """C++ 源码:lock_guard 声明所在行到它所在花括号块结束的那一行(从 1 起),交回 (起, 止)。"""
    lines = src.split("\n")
    start = None
    depth = 0
    for i, line in enumerate(lines, 1):
        if "lock_guard" in line and start is None:
            start = i
            depth = 0
        if start is not None:
            depth += line.count("{") - line.count("}")
            if depth < 0:
                return start, i
    return start, len(lines)

C_SRC = """int take(int k) {
  pthread_mutex_lock(&m);
  if (stock < k) return -1;
  stock -= k;
  pthread_mutex_unlock(&m);
  return stock;
}

void put(int k) {
  pthread_mutex_lock(&m);
  stock += k;
  pthread_mutex_unlock(&m);
}
"""
CPP_SRC = """int take(int k) {
  std::lock_guard<std::mutex> g(m);
  if (stock < k) return -1;
  stock -= k;
  return stock;
}
"""

leaks = find_leak(C_SRC)
lines = C_SRC.split("\n")
print(str(leaks) + "/" + lines[leaks[0] - 1].strip().replace(" ", "_"))
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论