본문으로 건너뛰기

[CPython] SyntaxError 재초기화 시 메모리 누수 수정

PR 링크: python/cpython#146517 (3.14), #146519 (3.13) 상태: Merged | 변경: +39 / -12 (3.14), +37 / -11 (3.13)

들어가며

Python에서 예외 객체의 __init__을 다시 호출하여 재초기화하는 것은 드물지만 가능합니다. SyntaxError의 C 구현에서 이 경로에 메모리 누수가 있었습니다. 기존 속성(filename, lineno 등)의 참조 카운트를 감소시키지 않고 새 값으로 덮어쓰면서, 이전 객체가 영원히 메모리에 남게 되었습니다.

핵심 코드 분석

Before:

// Objects/exceptions.c - SyntaxError_init()
self->end_lineno = NULL;
self->end_offset = NULL;
if (!PyArg_ParseTuple(info, "OOOO|OO",
                      &self->filename, &self->lineno,
                      &self->offset, &self->text,
                      &self->end_lineno, &self->end_offset)) {
    Py_DECREF(info);
    return -1;
}
Py_INCREF(self->filename);
Py_INCREF(self->lineno);
Py_INCREF(self->offset);
Py_INCREF(self->text);
Py_XINCREF(self->end_lineno);
Py_XINCREF(self->end_offset);

After:

PyObject *filename, *lineno, *offset, *text;
PyObject *end_lineno = NULL;
PyObject *end_offset = NULL;
if (!PyArg_ParseTuple(info, "OOOO|OO",
                      &filename, &lineno,
                      &offset, &text,
                      &end_lineno, &end_offset)) {
    Py_DECREF(info);
    return -1;
}
Py_XSETREF(self->filename, Py_NewRef(filename));
Py_XSETREF(self->lineno, Py_NewRef(lineno));
Py_XSETREF(self->offset, Py_NewRef(offset));
Py_XSETREF(self->text, Py_NewRef(text));
Py_XSETREF(self->end_lineno, Py_XNewRef(end_lineno));
Py_XSETREF(self->end_offset, Py_XNewRef(end_offset));

핵심 변경:

  1. 로컬 변수로 먼저 파싱: PyArg_ParseTuple의 결과를 self-> 멤버에 직접 쓰지 않고 로컬 변수에 먼저 받습니다
  2. Py_XSETREF 사용: 기존 값의 참조를 감소시키고(Py_XDECREF) 새 값을 대입합니다. Py_INCREF + 직접 대입과 달리, 이전 값이 존재하면 안전하게 해제합니다

왜 이게 좋은가

  • Py_XSETREF의 올바른 사용: 이 매크로는 "이전 값 해제 + 새 값 설정"을 원자적으로 수행합니다. 재초기화 시나리오에서 필수적인 패턴입니다.
  • 로컬 변수 분리: PyArg_ParseTuple이 실패할 때 self-> 멤버가 중간 상태에 놓이는 것을 방지합니다. 파싱이 성공한 후에만 멤버를 업데이트합니다.
  • 테스트 추가: 재초기화 후 모든 속성이 올바르게 업데이트되는지 검증하는 테스트가 포함되었습니다.

정리

SyntaxError.__init__() 재호출은 edge case이지만, CPython의 메모리 안전성을 위해 모든 경로가 올바르게 동작해야 합니다. Py_XSETREF는 C 확장에서 "이전 값 교체" 패턴의 정석이며, 이 PR은 그 모범적 적용 사례입니다.

참고 자료


이 포스트는 AI가 작성하였으며, 사실과 다를 수 있습니다. 정확한 정보는 원본 PR을 참고해 주세요.

댓글

관련 포스트

PR Analysis 의 다른글