Javascript 에 메모리 누수가 있습니까? 그렇다면, 그것을 피하는 방법은 무엇입니까? 최근 여러 분이 비슷한 질문을 하신 것으로 보아 이 부분에 대해 체계적으로 연구한 사람이 없는 것 같아 몇 년 전에 정리한 내용을 여러분께 전해드리려고 합니다.
우선, 적어도 IE6에서는 JavaScript를 작성하는 일부 방법으로 인해 메모리 누수가 발생할 수 있다는 점은 확실하게 말할 수 있습니다. 따라서 오늘날 IE6가 폐기를 거부하더라도 관련 지식을 이해해야 합니다(대부분의 경우 js로 인한 메모리 누수가 컴퓨터 속도를 저하시키는 주요 원인은 아니지만). 관련 연구는 주로 2005~07년에 집중되어 있으며, 이 글은 당시에 연구한 친구들이 있다면 그냥 무시해도 됩니다.
프론트엔드 개발자로서 이러한 문제를 이해하려면 문제가 무엇인지, 왜 그런지 알아야 합니다. 따라서 js 메모리 누수를 소개하기 전에 메모리 누수가 발생하는 이유부터 시작하겠습니다.
메모리 누수에 대해 이야기할 때는 메모리가 할당되는 방식에 대해 이야기해야 합니다. 메모리를 할당하는 방법에는 세 가지가 있습니다.
1. 정적 할당(Static Allocation): 정적 변수와 전역 변수의 할당 형태. 방을 프로그램으로 생각한다면 정적으로 할당된 메모리는 방에 있는 내구성 있는 가구로 생각할 수 있습니다. 일반적으로 매일 옷장을 쓰레기로 창밖으로 버리는 사람이 없기 때문에 방출하고 재활용할 필요가 없습니다.
2. 자동 할당: 스택의 지역 변수에 대한 메모리를 할당하는 방법입니다. 코드 블록이 종료되면 팝 작업을 통해 스택의 메모리가 자동으로 해제될 수 있습니다.
이는 일을 하러 방에 오는 사람들과 비슷하다. 일단 일이 끝나면 스스로 나가고, 그들이 나가면 그들이 차지한 공간이 자동으로 풀리게 된다.
3. 동적 할당(Dynamic Allocation): 데이터를 저장하기 위해 힙(heap)에 메모리 공간을 동적으로 할당하는 방법. 즉, 프로그램 실행 시 malloc이나 new를 사용하기 위해 적용된 메모리를 우리가 직접 free나 delete를 사용해 해제해야 한다. 동적 메모리의 수명은 프로그래머에 의해 결정됩니다. 해제하는 것을 잊어버리면 필연적으로 메모리 누수가 발생합니다. 이 경우 힙에 있는 메모리 블록은 우리가 매일 사용하는 냅킨과 같으며, 사용한 후에는 쓰레기통에 버려야 합니다. 그렇지 않으면 집이 엉망이 될 것입니다. 그러므로 게으른 사람들은 청소를 도와줄 가정용 로봇을 갖는 꿈을 꿉니다. 소프트웨어 개발에서 메모리를 확보하기에는 너무 게으른 경우 유사한 로봇도 필요합니다. 이는 실제로 특정 알고리즘에 의해 구현된 가비지 수집기입니다. JavaScript 메모리 누수를 일으키는 것은 정확히 가비지 수집 메커니즘 자체의 일부 결함입니다.
몇 년 전, 나는 쓰레기 수거 메커니즘에 대해 심층적으로 설명하는 "쓰레기 재활용의 흥미로운 역사"라는 기사를 읽었습니다.
많은 고급차들이 셀링 포인트로 활용했던 슈퍼차저 기술이 실제로 1910년대 메르세데스-벤츠가 사용했던 것처럼, 쓰레기 재활용 기술도 오래전부터 존재해왔다. 1960년경 MIT에서 탄생한 Lisp 언어는 동적 메모리 할당 기술에 크게 의존한 최초의 언어였습니다. Lisp의 거의 모든 데이터는 "테이블"의 형태로 나타나며 "테이블"이 차지하는 공간은 힙에 있습니다. 동적으로 할당됩니다. Lisp 언어의 고유한 동적 메모리 관리 기능을 사용하려면 Lisp 언어 설계자가 힙에 있는 각 메모리 블록의 자동 해제 문제를 해결해야 합니다(그렇지 않으면 Lisp 프로그래머는 필연적으로 프로그램의 수많은 free 또는 delete 문에 압도당하게 됩니다). 이는 가비지 수집 기술의 탄생과 발전으로 직접 이어졌습니다.
가장 기본적인 가비지 컬렉션 알고리즘 세 가지도 이때 함께 등장했다. 하나씩 살펴보겠습니다.
참조 계산 알고리즘: 이것이 가장 먼저 떠오르는 방법일 수 있습니다. 비유적으로 말하면, 참고카운팅은 집에 백서가 많은데, 이 백서는 추억과도 같다. 기억을 사용하는 것은 종이에 글을 쓰는 것과 같습니다. 메모리는 마음대로 사용할 수 있지만 종이를 사용하는 사람은 종이 모서리에 1의 숫자를 적어야 합니다. 두 사람이 동시에 종이를 사용하면 숫자가 1이 됩니다. 2 등. 사람이 종이 한 장을 다 사용하면 모서리에 있는 숫자를 1씩 감소시켜야 합니다. 이렇게 숫자가 0이 되면 쓰레기 수거 조건이 충족되고, 옆에서 대기하던 로봇이 즉시 종이를 쓰레기통에 던집니다. 쓰레기. 참조 카운터 기반 가비지 수집기는 더 빠르게 실행되고, 장시간 동안 프로그램 실행을 방해하지 않으며, 실시간으로 실행해야 하는 프로그램에 적합합니다. 그러나 참조 카운터는 프로그램 실행의 오버헤드를 증가시키는 동시에 또 다른 가장 큰 문제가 있습니다. 즉, 순환 참조가 생성되면 메모리가 누출됩니다. 예를 들어, 두 개의 객체 a와 b를 새로 만들었습니다. 이때 a와 b의 개수는 모두 1입니다. 그러면 a의 속성은 b를 가리키고 b의 속성은 a를 가리킵니다. 참조 관계에서 a와 b의 개수는 모두 2가 됩니다. 프로그램이 종료되고 범위를 종료하면 프로그램은 자동으로 a의 개수를 1만큼 감소시킵니다. 결국 a의 개수는 여전히 1이므로 a는 그렇지 않습니다. 마찬가지로 b의 최종 개수도 1이고 b는 해제되지 않으며 메모리가 누출됩니다!