time.h에 들어있는 time 함수는 어떻게 쓰일까요? 이 함수는 1970년 1월 1일 0시 0분 0초부터, 현재 시간까지 경과된 초를 리턴합니다. 예를 들어서 현재 시간이 1970년 1월 2일 0시 0분 0초라면, 86400이 리턴될 겁니다. 이 함수와 관련된 문제 중에는, 2038년 문제가 있는데요. 이것은 오버 플로우를 설명할 때 다시 언급해 드리도록 하겠습니다.

 

 


 

 time_t는, time_t의 포인터 변수를 받습니다. 그리고, 리턴하는 값 또한 time_t형인데요. 이것은 그냥 integer type이라고 생각하시면 편합니다. 그런데, 1번째 인자에 NULL을 넣을 수도 있고, time_t형 변수의 주솟값을 넣을 수도 있습니다. 다음 예제를 통해서, 이 두 가지 경우에 어떻게 동작하는지 보도록 합시다.

 

 

 먼저, NULL을 넣었습니다. 이 경우, 그냥 1970년 1월 1일 0시 0분 0초부터, 현재까지 몇 초가 지났는지를 리턴해 줍니다. ti에 그 값이 들어갈 겁니다. 다음에, 5번째 줄에 time_t형 u를 선언해 주었습니다. 그리고, u의 주솟값을 넘겼어요. 이 경우에는 어떻게 동작할까요?

 

 

 time_t형 변수인 u는 0x80번지에 저장이 되어 있습니다. 이것을 c언어 time 함수에 넘길 겁니다.

 

 

 그러면, 값 복사가 일어날 겁니다. time 함수가 받아온 매개변수는 u가 아닌, 0x80이라는 주솟값입니다.

 

 

 그리고, 현재 시간을 알아온 다음에, 1970년 1월 1일 0시 0분 0초부터 경과된 시간을 초 단위로 계산을 할 겁니다. 그 결과값을 res라고 해 봅시다. 이 때, 이 res의 값을 tar가 가리키는 주솟값에 write를 합니다. 즉 15621... 이라는 값이 u에 저장이 될 겁니다.

 

 

 실제로, 저는 이 프로그램을 2019년 7월 3일에 수행했습니다. 그렇기 때문에, u에 1562...가 저장이 될 것이고, 리턴된 값도 1562...가 될 겁니다. 그러면, 이 time 함수는 초 단위로 값이 바뀐다는 소리가 됩니다. 코드 포스에서 랜덤 풀이를 구현한 경우에, srand(time(NULL))을 썼다가 해킹을 당하는 주된 이유이기도 합니다. 이는 밑에서 다시 설명 드리겠습니다.

 

 


 실제로, time 함수는 srand와 같이 쓰이는 경우도 상당히 많습니다. 특히 랜덤 number라던지, 랜덤 풀이를 구현하려고 할 때 쓸 수 있는 것 중 하나입니다. 사실, rand는 그러한 기능을 구현할 수 있는 함수 중에서는, 꽤 쉽고 간단한 함수 중 하나입니다.

 

 이 친구는 또 srand라는 함수와 짝꿍으로 쓰이는 경우가 굉장히 많은데요.

 

 

 이 함수는 처음 시드값을 설정해 주는 함수입니다. 그런데 rand()는 특별한 인자가 없네요? 그런 걸로 봐서는 전역 변수를 내부에서 쓰는 것을 알 수 있는데요. 실제로, rand의 내부 구현에 대해서 간단히 검색해 보면, seed 값을 토대로, rand가 호출되면 값을 뽑아냅니다. 그리고 뽑아낸 값을 토대로 rand()를 호출하면 다시 그 값을 토대로 새로운 값을 리턴하는데요. 그 과정에서 전역 변수가 쓰입니다.

 

 그렇기 때문에, 쓰레드 안전하지 않다고 이야기 합니다. 그냥 rand() 계열은 이렇다는 것 정도만 간단히 짚고 넘어가시면 좋겠습니다. 그렇다면 시드 값이 같다면, 저 프로그램의 결과값도 모두 같을 건데요. 실제로 그런지 확인해 보겠습니다. 첫 시드를 15로 주었습니다.

 

 

 그러면, 프로그램을 여러번, 수 초가 지난 후에 다시 실행해도 똑같은 결과가 나온다는 것을 알 수 있어요. 즉, 첫 시드 값만 알고 있으면, random 넘버가 어떻게 출력되는지 알 수 있다는 겁니다. 그러면, 만약에 srand(time(NULL))을 준 경우는 어떨까요?

 

 time(NULL)은 1970년 1월 1일 0시 0분 0초부터 현재까지 경과된 시간을 초 단위로 리턴해 줍니다.

 

 

 그러면 1초 전에 수행한 프로그램이랑, 1초 후에 수행한 프로그램이랑 결과값이 다르게 나올 겁니다.

 

 

 실제로 저 코드를 컴파일 해서 수행을 시켜 보면, clock2를 굉장히 짧은 간격으로 실행시키면 결과값이 같음을 알 수 있어요. 시드 값을 알면, 저 랜덤 넘버들도 매우 쉽게 알 수 있어요.

 

 

 2019년 7월 3일 7시 18분 x초일 때, time 함수가 리턴하는 값은 얼마일까요? 1562145486에 많아봤자 3660을 더한 것일 겁니다. 만약에 ms 단위로 시드값을 리턴하게 했다면, 7시 18분 x초일 때 time함수가 리턴하는 값이 v라고 해 봅시다. 1000ms가 1초기 때문에, 1000v에서 1000v+999가 될 겁니다. 그런데, time 함수를 쓰면 7시 18분 x초 238이여도 v가 나올 거고, 7시 18분 x초 333이여도 v가 나올 겁니다.

 

 

 초 단위까지는 매우 쉽게 알 수 있어요. 특정한 시간에 대해서, 몇 년도 몇 월 몇 일 몇 시 몇 분 몇 초에 대한 정보를 미리 어딘가에 넣어놓고 그것들을 time_t로 바꿔버리면 어떨까요? 보통 srand(time(NULL))을, 프로그램이 시작하자 마자 쓰는 경우가 대부분일 겁니다. 그러면 대략적으로 프로그램을 실행시킨 시간에 +1 ~ 2초 정도까지 시드 값의 후보가 될 거에요. 시드값의 후보가 적다는 것은, 공격자의 입장에서는 매우 반가운 일이에요. 단 몇 개만 대입해보면 되기 때문입니다.

 

 다음에는, time_t를 통해서 날짜 데이터를 다뤄보도록 하겠습니다.