표준 C에서 문자열-실수 변환 오류를 이식성 있게 검출할 방법이 없다
No portable way to detect string-to-float conversion errors in standard C
표준 C의 strtod 계열 함수는 math_errhandling 매크로에 따라 errno나 부동소수점 예외로 오류를 보고한다. 하지만 POSIX는 항상 errno를 설정하도록 요구해 서로 충돌한다. 특히 musl은 잘못된 입력에 errno를 EINVAL로 설정하지만 glibc는 그렇지 않아, 이식성 있는 오류 검출이 사실상 불가능하다. 저자는 각 상황별 올바른 검사 방법을 정리하며 표준 문구의 명확화가 필요하다고 지적한다.
표준 C만 놓고 보면, 잘못된 입력은 오류 조건이 아니기 때문에 musl이 다른 문서화된 오류 조건이 있는 함수에서 errno를 0이 아닌 값으로 설정하는 것은 적합하지 않다.
HN 토론
56- Joker_vD
흔히 쓰이는 프로그래밍 언어들(FORTRAN부터 Java/C#까지)이 함수 호출에서 두 개의 값을 인체공학적으로 반환하지 못했던 역사적 무능력이 얼마나 놀라운 결과를 낳았는지, 사람들이 온갖 미친 API/계약을 발명하게 만들었다.
[double x, errno_t errno] = strtod(s, nullptr);
if (errno != 0) {
// ...
}
[x, _] = strtod(s, nullptr); // 오류가 불가능하다고 확신하거나 신경 쓰지 않을 때
그 대신 우리는 기껏해야 "반환값이 -1인지 확인하고, 그렇다면 전역 변수 errno를 확인하라"에 머물러 있고, 최악의 경우 "이 함수는 오류를 제대로 보고하지 않으니 잘못된 데이터를 넣지 마라, 알 바 아니다"에 머물러 있다.
- Panzerschrek
C 숫자 파싱 함수들은 근본적으로 망가져 있다. 왜냐하면 로케일에 의존하기 때문이다. 소수점이 있다고 가정하고 숫자를 파싱했는데, 나중에 개발자 머신과 다른 로케일을 가진 시스템에서는 갑자기 점 대신 쉼표가 될 수 있는 버그가 많다. 따라서 거의 항상 이들을 피하고 std::from_chars(새 C++ 버전에서 사용 가능)나 다른 서드파티 라이브러리를 사용해야 한다.
- gucci-on-fleek
> 이 함수들에 대한 리눅스 man 페이지는 이 점을 전혀 언급하지 않는다
> man 페이지가 이것이 확장 기능이라는 점을 전혀 언급하지 않는다는 사실이 ([…]) 정말 눈에 띈다.
> 이것은 리눅스 man 페이지에 완전히 문서화되어 있지 않다.
내 경험상 리눅스 man 페이지 관리자들은 정말 친절하니, 이 문제를 그들에게 보고할 가치가 있을 것이다 [0] [1].
[0]: https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/...
- Kevin_Flynn
> 표준 C에서 문자열-실수 변환 오류를 검출할 이식성 있는 방법이 없다
표준 C는 하나가 아니라 여러 개다. AI는 5개라고 한다.
주요 ISO C 표준은 5개다: C90, C99, C11, C17/C18, C23. C89는 본질적으로 ANSI 이름 아래의 C90과 같은 표준이고, C95는 별도의 주요 에디션이 아니라 수정안이었다. 최신은 C23이다.
POSIX는 아시다시피 "Portable Operating System Interface"의 약자다.
> posix는 math_errhandling에 관심이 없다; 오버플로나 언더플로가 발생하면 항상 구현이 errno를 설정하도록 요구한다.
그래서 "Portable" 인터페이스인 POSIX는 언더플로/오버플로 오류가 항상 보고되도록 명시한다.
문제는 명세가 아니라 헤드라인에 있는 것 같다.
- RossBencina
오랫동안 마이크로소프트의 strtod 구현은 망가져 있었다. 대부분의 사람들은 netlib나 새로운 알고리즘 중 하나를 사용할 것이라고 생각한다.
https://www.exploringbinary.com/visual-c-plus-plus-strtod-st...
https://lemire.me/blog/2026/02/01/converting-floats-to-strin...