코드에 좌표가 10만을 넘으면 무시하는 줄이 있었다. 왜 좌표가 그렇게 커지는지 아무도 몰랐다.
Table of contents
Open Table of contents
지우려다 세어 봤다
쓸데없어 보였다. 좌표가 10만을 넘을 일이 없기 때문이다. 지우기 전에 얼마나 걸리는지 CCLOG 를 넣고 하루 돌려 봤다.
[guard] 이상한 좌표 x=nan y=nan
... 1,842건
하루에 1,800번 걸리고 있었다. 지웠으면 그만큼이 그대로 나갔다. 막아 둔 것이 있다는 것은 그 문제가 실제로 있었다는 뜻이다.
왜 그 값이 나오는지 찾았다
NaN 이었다. 처음에는 각도를 구하는 atan2 를 의심했는데 그건 두 값이 다 0이어도 0을 돌려준다. 실제로 짜 보고 확인했다.
NaN 이 나는 자리는 방향을 단위 길이로 만드는 쪽이었다. 두 유닛이 정확히 같은 자리에 있으면 sqrt 로 구한 길이가 0이고 거기서 나누면 0/0 이 된다.
if (fabs(dx) < 0.0001f && fabs(dy) < 0.0001f) {
return; // 같은 자리다. 나눌 길이가 없다
}
같은 자리면 방향을 구할 것이 없으므로 그 앞에서 돌아가게 했다. NaN 은 한 번 생기면 그것이 낀 계산이 전부 NaN 이 되어서 원래 자리가 안 보인다. IEEE 754 가 그렇게 정하고 있다. 그래서 나는 자리에서 막아야 했다.
막아 둔 것은 남겼다
원인을 고쳤으니 막아 둔 것을 지울까 했는데 남겼다. 다른 경로로 또 생길 수 있기 때문이다. 검사도 isnan() 을 쓰게 바꿨다. NaN 은 자기 자신과도 같지 않아서 크기 비교로는 안 걸리는 경우가 있다.
대신 왜 있는지와 언제 무엇을 고쳤는지를 적었다. 안 적으면 다음 사람이 또 쓸데없어 보인다고 지운다.
고친 뒤에 다시 세어 보니 하루 1,842건이 3건이 됐다. 3건이 남았다는 것은 다른 경로가 있다는 뜻이었고 로그를 보니 0으로 나누는 자리가 따로 있었다. 막아 둔 것을 지웠으면 이 3건은 영영 못 찾았다.
다른 확인들의 횟수
같은 방식으로 코드에 있는 다른 확인들도 세어 봤다. 대부분 0건인데 하나가 하루 412건 걸리고 있었고 그것도 조사 대상이 됐다.
0건인 것은 그냥 뒀다. 안 걸린다고 지울 이유가 없다. 걸릴 때를 위한 것이기 때문이다.
다만 0건인 것과 세어 보지 않은 것은 다르다. 세어 보고 0인 것은 지금 안 걸린다는 사실을 아는 것이고 안 세어 본 것은 아무것도 모르는 상태다.
CCLOG 가 많으면 그것대로 부담이라 개발 빌드에서만 찍게 하고 운영에서는 횟수만 세어 가끔 서버로 보냈다.
정리
- 이유를 모르는 막아 둔 것이 있으면 지우기 전에 얼마나 걸리는지 센다
- 걸리는 횟수가 그 문제의 크기다
atan2는 두 값이 0이어도 0을 돌려준다. 의심하기 전에 짜 본다NaN은 길이 0으로 나눌 때 나고 낀 계산을 전부NaN으로 만든다NaN검사는 크기 비교가 아니라isnan()으로 한다- 원인을 찾아 고치되 막아 둔 것은 남기고 이유를 적는다
- 고친 뒤에도 세어 본다. 남은 횟수가 다른 경로를 알려 준다
- 안 걸린다고 지울 이유는 없다