나무모에 미러 (일반/밝은 화면)
최근 수정 시각 : 2024-11-02 17:42:19

오버플로

오버플로우에서 넘어옴

파일:나무위키+유도.png  
은(는) 여기로 연결됩니다.
동음이의어에 대한 내용은 오버플로(동음이의어) 문서
번 문단을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
참고하십시오.
1. 개요2. 원인3. 분류
3.1. 10진수 오버플로3.2. 8비트 오버플로3.3. 16비트 오버플로3.4. 32비트 오버플로3.5. 64비트 오버플로3.6. 기타
4. 관련 문서

1. 개요

Overflow
파일:external/imgs.xkcd.com/cant_sleep.png
xkcd 571화 'Can't Sleep'[1]
파일:기계식 체중계 오버플로.jpg 파일:IMG_6133~2.png
기계식(아날로그) 체중계가 측정 범위를 넘어 버린 모습.[2] 네이버 날씨에서 모종의 오류로 오버플로가 발생한 상황.[3] -우주종말-

컴퓨터의 정수 연산의 계산 결과가 허용 범위를 초과할 때 발생하는 오류.[4]

2. 원인

파일:상세 내용 아이콘.svg   자세한 내용은 컴퓨터에서의 수 표현 문서
번 문단을
부분을
참고하십시오.
컴퓨터의 메모리가 8비트의 데이터를 저장할 수 있다고 하고 편의상 부호는 없는 양수인 경우만 고려해 보자. 가장 작은 값은 0000 0000 (=0) 이며, 1씩 증가시키면 0000 0001(=1)을 거쳐 최댓값인 1111 1111 (=255)에 도달하게 된다. 여기에서 1을 다시 한 번 더하게 되면 최댓값의 범위를 넘어서게 되고 최솟값인 0000 0000(=0)으로 되돌아가게 된다. 이를 오버플로라고 부른다.

이는 2의 보수를 사용하는 부호형 정수 방식(signed integer)에서도 동일하며 8비트 정수형은 -128 ~ 127 사이의 값을 저장할 수 있다. 그런데, 0111 1111(=127)에서 1을 더하게 되면 1000 0000인데 이는 -128이 된다. 이 역시 최댓값의 범위를 넘어서서 가장 작은 값으로 바뀌는 것이다.

32비트 부호형 정수형이라면 -2147483648 ~ 2147483647이며 이 경우에도 2147483647 + 1은 허용범위를 초과하므로 최솟값인 -2147483648가 된다. 반대로 정수의 최솟값에서 1을 뺄 경우에는 최댓값이 되어 버린다. 즉ㅡ=, -2147483648 - 1 = 2147483647이 된다. 일부 사람들이 이를 언더플로라고 부르지만 잘못된 표현이며 이 경우도 오버플로라고 부르는게 맞다. 양이건 음이건 범위를 벗어나면 모두 오버플로이다. 산술 언더플로(Arithmetic underflow)는 부동소수점 연산에서 지수부가 타입의 한계를 넘어 작아지면 0에 가까워지다가 결국 0이 되어버리는 현상을 의미한다. 하지만, 정수 자료형에서 최댓값에서 최솟값으로 넘어가는 오버플로와 구분하기 위해 언더플로라는 용어를 혼용해서 사용하고 있는데 명확하게 하기 위해서는 '정수 언더플로'(Integer underflow)라는 용어를 사용해 산술 언더플로와 다르다는 것을 명시하는 것이 좋다.

오버플로의 가장 많은 예로 스택 오버플로(Stack Overflow)가 있다. 함수는 변수 등을 저장하기 위해 스택이라는 메모리 공간을 만드는데 이 함수가 재귀적으로 계속 실행되면 스택이 점점 생겨난다. 이러면 어느 순간 메모리가 모자라는 순간이 찾아오는데 이때 생기는 오류다. 프로그래밍 언어를 만들 때 스택 오버플로가 잘 일어나지 않도록 하는 것도 일이다. 응용형으로 버퍼 오버플로(Buffer overflow)가 있다. 할당된 범위의 메모리를 벗어난 주소로 접근하게 되는 것으로, 하트블리드 사태도 버퍼 오버플로로 인해 벌어진 것이다.

컴퓨터 또는 프로그래밍 언어의 동작에 따라 오버플로 발생 시 오류 메시지를 출력하는 경우도 있고[5] 그러지 않는 경우도 있다. 이 중 오류 메시지를 출력하지 않는 경우가 더 위험하다. 잘못된 정보로 명령을 계속 수행하므로 잘못된 값을 출력하거나 오류 메시지를 출력하는 곳과 오버플로가 일어난 곳이 다른 일이 일어날 수 있다. 일부 프로그래밍 언어는 오버플로가 일어나지 않도록 언어 자체적으로 보완책을 가지는 경우도 존재한다.

3. 분류

3.1. 10진수 오버플로

10진수 기반 시스템에서 발생하는 오버플로다.


최대 9999까지 표현 가능한 기기에서 9999에 1을 더할 때 발생하는 10진수 오버플로. 이 현상은 일상에서도 흔히 볼 수 있다.

파일:무료입니다.gif

무슨 차길래 기름이 1000달러나 들어가는...[6]

초창기의 컴퓨터는 BCD(Binary Coded Decimal) 나 EBCDIC(Extended Binary Coded Decimal Interchange Code)이라 불리는 10진수 기반의 수체계를 사용했으며 이 당시 사용하던 코볼(COBOL) 같은 컴퓨터 언어도 이런 수체계 기반을 사용하도록 만들어져 있었다. 그래서 99나 999를 넘어가면 100이나 1000이 되는 것이 아니라 0이 되어 버리는 버그가 존재했다.

이로 인해서 가장 문제가 되었던 것이 바로 2000년 문제이다. 년도를 저장할 때 저장공간 압축을 위해 4자리가 아니라 2자리의 십진수 정수형을 사용하다 보니 (19)99년 다음에 올 (20)00년을 (19)00년으로 인식하지 않을까 하는 문제가 대두된 것이다.[7] 덕분에 전 세계 프로그래머들은 1999년 말에 엄청나게 갈려나갔다고 한다.

3.2. 8비트 오버플로

8비트 정수의 저장 범위는 최상위 비트를 음수 부호로 사용하는(signed) 경우 -128 ~ 127이고 음수 부호를 사용하지 않는(unsigned) 경우 0 ~ 255이다. 255나 127을 넘어갈 경우 오버플로가 발생한다.

3.3. 16비트 오버플로

16비트 정수의 저장 범위는 -32768 ~ 32767(signed) 또는 0 ~ 65535(unsigned)이다. 65535나 32767을 넘어갈 경우 오버플로가 발생한다.

3.4. 32비트 오버플로

32비트 정수의 저장 범위는 대략 -231 ~ 231-1(signed) 또는 0 ~ 232-1(unsigned)까지인데 이 값을 넘어갈 경우 오버플로가 발생한다. 이 값들을 풀어 쓰면 42949672952147483647인데 관련 버그에서 흔히 등장하는 값이다. 다만 고정소수점 사용이나 최종 저장은 다른 데이터 형식을 쓰는 경우 214만 등의 변종이 나올 수 있다.

3.5. 64비트 오버플로

파일:92fe5412eb33465ac.jpg

[18]

64비트 오버플로도 존재하지만 signed int라도 9223372036854775807이라는 상당히 큰 수를 넘겨야 하기 때문에 어지간한 파워 인플레가 아닌 이상 발생하는 일은 거의 없다. 시간으로 오버플로가 발생하려면 2922억년을 기다려야 한다. 2922억 년 뒤의 나무위키 편집자가 문서를 수정하면 된다

비교적 쉽게 볼 수 있는 사례로는 스텔라리스가 있다. 현재 64비트 고정소수점을 써서 184조쯤[19]에서 오버플로가 일어나는데# 모딩이 활성화된 게임이라 소위 (파워 인플레) 뇌절 모드 여러개로 시너지를 일으키면 쉽게 넘길 수 있다. 해킹이나 치팅을 포함하면 더욱 쉬운데 숫자 놀음 아이들 플래시 게임은 배정밀도 부동소수점(64비트 표준 실수 표현형)을 많이 써서 해킹으로 10^302 정도로 올려도 정상 처리되고 심지어 한계(대략 10^303~304 정도)를 넘겨 오버플로가 나도 게임 진행은 정상적으로 되는 경우도 있다.[20]

3.6. 기타


여러 기기의 설정 가능한 최대 날짜를 넘겨서 오버플로를 실험해 보는 영상. 각종 OS, 전자기기, 프로그래밍 언어를 테스트했다.[21]

4. 관련 문서



[1] 32767에서 -32768로 나가는 걸로 봐서 이 예시에서 양의 수는 부호 있는 2바이트 정수 형태(short)로 저장되는 모양이다.[2] 실제 무게는 131.5kg인 것으로 추정된다. 지난 측정값인 117kg에서 14kg 이상 찐 것.아무리 오버플로라도 이건 막장인데? 도대체 무슨 일이 있었길래... 사진 한 장만으론 앞뒤 정황을 알 수 없으니 영점이 틀어져서 실제보다 수kg~십수kg 정도 더해져서 오버플로가 된 것이거나 체중계의 측정 범위를 초과한 게 아니라 체중계의 바늘이 고장나서 1.5kg에서 걸려 멈춘 걸 수도 있다. 물론 어느 쪽이든 사람이 알아채기 쉬운 증상을 보이므로(전자는 체중계에 올라가기 전 바늘이 이미 10kg 전후를 가르키고, 후자는 바늘이 돌아가는 모습 없이 그냥 멈춰야 한다) 실제로 그랬다면 일종의 낚시가 된다.[3] 참고로 절대영도는 약 영하 273.15도이다.[4] 원래 나와야 할 값 대신 필요없는 값이 나온다고 '쓰레기 값'이라고 부르기도 한다. 다만 쓰레기 값이라는 말 자체는 메모리를 초기화하지 않고 사용해서 그 전에 그 자리를 점유하던 임의의 값이 참조되는 등 여러 이유로 사용하기 곤란한 값이 나올 때 쓰이는 좀 더 광범위한 말이다.[5] 프로그래머가 코딩을 하며 catch, try 등으로 예외 처리를 했으면 오류 메세지가 뜬다. 보통은 '메모리가 XXXXXX~YYYYYY 값을 초과하였습니다. 이 메모리는 read될 수 없습니다' 와 같이 뜬다.[6] 보험 가입이 거부되는 호머를 보고 마지의 강박적인 절약으로 인해 생긴 돈을 빼돌려 구매한 캠핑카이다. 뒤의 조금 작은 00은 센트 단위다. 짤방 속 마지막에 나오는 문구는 스페인어로 '휘발유 공짜!'[7] 현재는 허무맹랑할 이야기뿐이지만 당시에는 실제로 일어난 일들이다. 당연히 컴퓨터는 문제가 없으나 컴퓨터에 돌아가는 프로그램을 사람이 짰으니까... 도서 반납을 새천년에 했더니 컴퓨터가 1900년부터 대여한 것으로 인식해 100년치의 반납금을 산정한 일, 1900년 출생자들에게 입영통지서날아간 일... 다만 너무 나가서 금융망이 붕괴한다느니 방사능이 유출된다느니 등의 정말 말도 안 되는 소리까지 나오기도 했다.[8] 여기서 월드를 나타내야 할 칸이 빈칸으로 나오는 것도 오버플로 때문인데 사실은 월드 36이지만 프로그램에서는 36을 빈칸으로 인식하여 나타나는 것이다. 사실 마이너스 월드는 오버플로라기보다는 포인터가 잘못 동작한 것에 더 가깝기는 하다.[예시] /give @p diamond_sword{Enchantments:[{id:"sharpness",lvl:32767}\]} 라고 입력하면 날카로움 32767의 다이아몬드 검을 얻지만, /give @p diamond_sword{Enchantments:[{id:"sharpness",lvl:32768}\]} 이라고 입력하면 날카로움 -32768의 검을 얻게 된다. 때리면 몬스터가 치료되는 마법의 검.[예시2] 테이크다운에서 파이퍼가 80~90개 이상 파워 큐브를 수집#[11] 9시간 6분 8초이다.[12] 이때 얻는 캡의 갯수는 65535에서 가지고 있는 칩 갯수를 뺀 만큼 얻는 지라 칩이 32768캡에 가까울수록 얻는 캡이 많아진다.[13] 이는 광속의 약 2배에 달하며 당연히 현실에서는 상대성 이론에 의해 불가능하다.[14] 엄밀히 말하면 두 터치 간격이 30ms 이하여야 한다.[15] 즉, 장비가 부족한데 군대를 계속 만들면.[16] 레벨의 이름 마지막 글자가 숫자가 아니라면 2를 붙이고, 숫자라면 1을 더해서 복사된다. 예: Stereo Madness 2를 복사 → Stereo Madness 3이 되어 크리에이트 창에 저장.[17] 영상을 보면 표기로도 시스템으로도 -21억인지 코인을 1원 조차 쓸수 없고, 재료를 팔면 표기상 코인이 오르긴 오르나 터무니 없이 부족한 양이다.[18] 만화를 해석하자면 지니가 건넨 조건은 '소원을 늘리면 안된다' 였기 때문에 '소원을 줄이는 것'은 가능하다. 여기서 소원자가 말한 갯수 타입인 unsigned long long(unsigned 64bit int)은 표현 가능한 숫자 범위가 0 ~ 18446744073709551615까지인데 마지막 소원 1개가 남은 시점에서 '남은 소원의 갯수를 1개 줄여달라'는 소원을 썼고 그 소원을 사용한 것 자체로 갯수가 소진되어 0이 되었는데 소원의 내용대로 추가로 -1이 발생한다. 여기서 오버플로가 발생하면 평생 소원을 사소한 것에 내다 버려도 다 쓰지 못할 양수 18,446,744,073,709,551,615의 소원 갯수가 된다.[19] 초기 버전은 32비트 고정소수점이라 210만 쯤에서 오버플로가 발생했다.[20] 해당 수치는 (오류로 게임이 꺼지지 않았다면) 편의상 무한으로 표시되는 경우가 대부분이다. 다만 내부적으로는 0과 똑같이 취급해서 해당 자원을 못 쓰게 되는 경우도 많다.[21] 기기에 따라 반응이 다른데 무한정으로 늘어나거나, 기기에 저장된 가장 이른 날짜로 설정되거나 설정할 수 있는 최대치 이후의 날짜로 옮겨가기도 한다.[22] 게다가 이 기기의 코드는 단 한 명의 아마추어 코더가 작성한 것으로 밝혀졌고, 이 일련의 사태 이후 FDA는 의료기기에 쓰이는 코드 다큐멘테이션을 의무화했다. 오늘날 이 사태는 IT 윤리 분야에서 널리 인용되는 케이스로 남아있다.[23] 999999까지 표시되어 이를 넘겨도 계속 999999로 표시된다든가[24] 애초에 표시만 제한한 경우거나, 직접 구매만 불가능할 뿐이지 채집 등으론 얻을 수 있다던가, 특정 글리치를 통해 얻을 수 있다던가 등