[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));
핵심 변경:
- 로컬 변수로 먼저 파싱:
PyArg_ParseTuple의 결과를self->멤버에 직접 쓰지 않고 로컬 변수에 먼저 받습니다 Py_XSETREF사용: 기존 값의 참조를 감소시키고(Py_XDECREF) 새 값을 대입합니다.Py_INCREF+ 직접 대입과 달리, 이전 값이 존재하면 안전하게 해제합니다
왜 이게 좋은가
Py_XSETREF의 올바른 사용: 이 매크로는 "이전 값 해제 + 새 값 설정"을 원자적으로 수행합니다. 재초기화 시나리오에서 필수적인 패턴입니다.- 로컬 변수 분리:
PyArg_ParseTuple이 실패할 때self->멤버가 중간 상태에 놓이는 것을 방지합니다. 파싱이 성공한 후에만 멤버를 업데이트합니다. - 테스트 추가: 재초기화 후 모든 속성이 올바르게 업데이트되는지 검증하는 테스트가 포함되었습니다.
정리
SyntaxError.__init__() 재호출은 edge case이지만, CPython의 메모리 안전성을 위해 모든 경로가 올바르게 동작해야 합니다. Py_XSETREF는 C 확장에서 "이전 값 교체" 패턴의 정석이며, 이 PR은 그 모범적 적용 사례입니다.
참고 자료
이 포스트는 AI가 작성하였으며, 사실과 다를 수 있습니다. 정확한 정보는 원본 PR을 참고해 주세요.
관련 포스트
PR Analysis 의 다른글
- 이전글 [CPython 3.13] SyntaxError 재초기화 시 메모리 누수 수정 (backport)
- 현재글 : [CPython] SyntaxError 재초기화 시 메모리 누수 수정
- 다음글 [triton] AMD GPU Descriptor Encoding 최적화 패스 추가
댓글