역대급으로 밤새면서 한 말록........ 디버깅을 이렇게까지 해본건 처음인 듯. 일요일 저녁에 구현 끝났는데 수요일 오후에 해결함.. 결국 다 풀진 못했지만 스스로 해냈다는 데에서 뿌듯하긴 했다!
if문 내에서 변수 할당하는 새로운 문법을 알았다. if((x=y)==z)라고 쓰면 x에y를 할당한 뒤 z와 비교한다. 괄호는 빼먹으면 안된다.GET 함수를 따로 만든 것이었다. 매번 괄호며 우선순위 신경쓰지 말라고.optimized out 에러가 났다. 찾아보니 컴파일 과정에서의 최적화 문제라고 해서 최적화 단계를 낮췄더니 해결되었다. 참고 링크ALIGN은 원하는 크기를 넣으면 8 이하 자리 숫자를 버려서 반올림해주는게 맞다. 그랬다가 버림때문에 넣은 값보다 크기가 작아지면 안되니까 DSIZE-1인거고.SIZE_T_SIZE는? size_t의 크기만큼을 align 하는데, size_t를 까보면 unsigned long형이다. 지금 하는 32bit에서는 그게 4바이트이기 때문에 SIZE_T_SIZE가 8바이트가 되는거고 64비트 시스템에서는 16바이트가 될 것이다. 결국 DSIZE만큼인데, 운영체제가 바뀔 때 마다 DSIZE의 상수값을 바꿔줘야 하니까 DSIZE를 자동 계산하도록 한 것으로 보인다.explicit 구현할 때, adress ordering으로 하든 LIFO로 하든 free할 때의 복잡도는 크게 달라지지 않는다. adress ordering은 linked list의 앞뒤가 물리적으로 인접한 블록이기때문에 그걸로 coalesce하면 되고, LIFO는 링크드리스트의 predecessor와 successor로 이어진 블록이 물리적으로 인접한 블록은 아니기 때문에 implicit에서 했던 것처럼 HDRP(PREV_BLKP()) 해서 찾으면 되는 것이었음.find_fit의 while문 조건을 현재 bp의 푸터+WSIZE 위치의 사이즈를 가져오면 그게 에필로그에서 GET_SIZE한 것이기 때문에 0이 될거라고 생각했나보다. 그게 0이 되면 while문을 빠져나가서 NULL을 리턴하기. 근데 이러면 메모리가 부족해지는 이유는 맨 처음 init하고 블록이 하나만 있을 때는 무조건 while문의 조건이 0이 되기 때문에 NULL을 리턴하게 된다. 그럼 맨 처음 할당은 무조건 extend를 한번 하고 시작하게 되는거! 그러면 extend한 뒤에도 coalesce를 하기 때문에 같은 위치의 bp를 리턴하게되고 그럼 또 find를 못 찾기 때문에 무한 extend->find->extend...가 되는거 아닌가? 했는데 한번 extend를 한 뒤에는 find를 다시 하지 않고 바로 place를 해버리기 때문에 그건 아니었다. 대신 발견한 문제는 while문 첫번째 조건이 size<asize일 때 안됐던 것은 while문이 앞에서부터 돌면서 확인하는데, 지금 확인하는 블록은 asize보다 작지만 그 뒤의 블록은 asize보다 클 수 있다는 점이었다. 그러면 그 뒤의 블록을 할당하면 되는 건데 그게 안되고 while문을 빠져나가서 NULL을 리턴해버리는 문제였다.HDRP가 bp를 char 타입으로 변경해서 연산하는 이유가 뭔가 싶었는데 겨우 알아냈다. 포인터에 정수 사칙연산은 포인터가 가리키는 타입만큼 정수에 곱해서 이루어진다. 근데 우리는 WSIZE만큼 더하거나 빼고 싶은데 이건 바이트 단위이기 때문에 bp를 바이트 단위만큼 연산시키기 위해 char 타입으로 바꾸는 것! 그럼 헤더가 사실은 int 정보를 가지고 있는데 char 타입으로 리턴하는게 괜찮냐 하면은 사실은 안괜찮다. 포인터를 제대로 쓰려면 unsigned int* 타입으로 다시 바꿔줘야 함. 근데 우리가 지금까지 괜찮았던 건 HDRP랑 FTRP를 항상 GET_SIZE랑 GET_ALLOC 안에서 쓰는데 여기서 GET함수를 통해 타입을 바꿔주고 연산하기 때문이었다. 사실은 그냥 넣어준 걸로 보이는 식들도 다 PUT을 통해 넣어주기 때문에 괜찮은거였음.WSIZE, DSIZE만큼 움직이는 게 바이트대로 움직이는 것이기 때문에 char로 변환해서 움직여야 한다. arr+i하면 arr의 타입*i만큼 움직여서 i번째 주소를 가져오는 것과 같은 원리. 근데 그걸 주소값으로 저장하고 싶거나 불러오고 싶으면 unsigned int*형으로 변환해야 한다. 심지어 리턴할때는 void형으로 리턴해야 함!coalesce에서 연결을 잘못 해줬던 거였다. 뭔가 계속 안될때는 반례를 보면서 찾지 말고 로직을 검토하자. 민규오빠 말이 맞았음. 어차피 로직이 틀린건데 반례만 고치면 다른 반례가 또 나오고 나중에는 코드가 덕지덕지 누더기가 된다.find함수를 매번 coalesce 들어갈 때 마다 실행하지 말고 if문 안에 넣어서 네 경우 중 한번만 실행하도록 했더니 속도 때문인지 10점이 올랐다.