programing

메모리 누수는 괜찮은가?

prostudy 2022. 5. 11. 22:03
반응형

메모리 누수는 괜찮은가?

C 또는 C++ 응용 프로그램에서 메모리 누수가 발생한 적이 있는가?

일부 메모리를 할당하고 응용 프로그램의 마지막 코드 행(예: 전역 개체의 소멸자)까지 사용하면 어떻게 하시겠습니까?시간이 지남에 따라 메모리 소비량이 증가하지 않는 한, (Windows, Mac, Linux에서) 애플리케이션이 종료될 때 OS를 신뢰하여 메모리를 확보해도 괜찮으십니까?OS에 의해 해제될 때까지 메모리가 계속 사용 중이라면 실제 메모리 누수로 간주하시겠습니까?

만약 제3의 도서관이 당신에게 이 상황을 강요했다면?제3자 도서관이 아무리 훌륭해도 그 도서관 이용을 거절하겠는가?

나는 단 한 가지 실질적인 단점만을 볼 수 있는데, 그것은 이 양성적인 누출이 메모리 누수 감지 도구를 거짓 양성으로 나타낼 것이라는 것이다.

아니요.

전문가로서, 우리가 스스로에게 물어서는 안 되는 질문은, "이런 일을 하는 것이 과연 괜찮은가?"가 아니라, "이런 일을 하는 좋은 이유가 있는가?"이다.그리고 "기억의 유출은 고통이다"는 것은 좋은 이유가 아니다.

나는 일을 단순하게 하는 것을 좋아한다.그리고 간단한 규칙은 내 프로그램에 메모리 누수가 없어야 한다는 것이다.

그것은 내 삶도 단순하게 만든다.메모리 누출을 감지하면 '허용되는' 메모리 누수가 아닌지 판단하기 위해 정교한 의사결정 트리 구조를 거치지 않고 제거한다.

컴파일러 경고와 비슷한데, 이 경고가 내 특정 애플리케이션에 치명적일까?아닐 수도 있다.

하지만 그것은 궁극적으로 전문적인 규율의 문제다.컴파일러 경고를 묵인하고 기억력 누출을 용인하는 것은 결국 내 뒤통수를 칠 나쁜 습관이다.

극단적으로 말하자면, 외과의사가 수술 장비 일부를 환자 안에 두는 것이 과연 받아들여질 수 있을까?

해당 장비를 제거하는 데 드는 비용/위험이 해당 장비를 보관하는 비용/위험을 초과하고 무해한 상황이 발생할 수 있지만, SurgeonOverflow.com에 게시된 이 질문을 보고 "아니오" 이외의 다른 답변을 보게 된다면 의약품에 대한 나의 신뢰가 심각하게 훼손될 것이다.아이칼 전문직

만약 제3의 도서관이 이 상황을 나에게 강요했다면, 그것은 내가 문제의 도서관의 전반적인 질을 심각하게 의심하게 만들 것이다.마치 내가 자동차를 시험 운전해서 컵 홀더들 중 한 곳에서 세탁기와 견과류 몇 개가 헐렁한 것을 발견한 것 같다. 그 자체로 큰 문제는 아닐지 모르지만, 품질에 대한 의지가 부족함을 보여 주기 때문에 나는 대안을 생각해 볼 것이다.

나는 그렇게 하지 않는 한 메모리를 확보하지 않는 것은 항상 잘못된 것이라는 인기 없지만 실용적인 답변을 할 이다.예를 들어, 평생 동안 사용할 데이터 세트를 로드하기 위해 단일 할당 또는 일련의 할당을 수행하는 프로그램은 어떤 것도 자유롭게 할 필요가 없다.매우 동적인 메모리 요구 사항이 있는 대형 프로그램의 더 일반적인 경우(예: 탭/문서/기타 닫기)에는 더 이상 사용하지 않는 메모리를 가능한 한 빨리 확보해야 하지만 사용자가 "퇴장"을 선택할 때 어떤 것도 확보할 이유가 없으며, 그렇게 하는 것은 실제로 사용자 ex ex에게 해롭다.지각 있는

왜? 기억을 자유롭게 하는 것은 감동적인 기억을 필요로 한다.시스템의 malloc 구현이 할당된 메모리 블록에 인접한 메타데이터를 저장하지 않더라도, 당신은 단지 당신이 자유롭게 할 필요가 있는 모든 포인터를 찾기 위해 걷는 재귀적 구조가 될 것이다.

프로그램이 대량의 데이터를 처리했지만 한동안 대부분의 데이터를 건드리지 않았다고 가정해 보십시오(또한 웹 브라우저가 좋은 예임).사용자가 많은 앱을 실행 중인 경우 해당 데이터의 상당 부분이 디스크로 스왑되었을 가능성이 높다.만약 당신이 메인(0)에서 막 나가거나 돌아오면, 그것은 즉시 빠져나간다.탁월한 사용자 환경.만약 당신이 모든 것을 자유롭게 하려고 애쓰게 된다면, 당신은 5초 혹은 그 이상의 시간을 모든 데이터를 다시 교환하는 데 할애할 수 있다, 단지 그 직후에 그것을 버리기 위해서일 뿐이다.사용자의 시간 낭비.노트북의 배터리 수명 낭비.하드 디스크의 마모 낭비.

이것은 단지 이론적인 것만은 아니다.너무 많은 앱이 로드되고 디스크가 스레싱되기 시작할 때마다 "종료"를 클릭할 생각도 하지 않는다.나는 가능한 한 빨리 터미널에 도착해서 killall -9를 타이핑한다. 왜냐하면 나는 "출구"가 그것을 더 악화시킬 것이라는 것을 알기 때문이다.

'사용'되고 있는 기억의 양이 계속 커지지 않는 한 메모리 누수로 간주하지 않는다.이상적이지는 않지만 일부 미공개 메모리를 갖는 것은 필요한 메모리 양이 계속 증가하지 않는 한 큰 문제가 아니다.

이론적으로는 아니다, 실제론 그것은 다르다.

그것은 정말로 프로그램이 얼마나 많은 데이터를 작업하고 있는지, 얼마나 자주 프로그램을 실행하는지, 그리고 그것이 지속적으로 실행되는지에 달려있다.

적은 양의 데이터를 읽는 빠른 프로그램이 계산을 하고 나간다면 작은 메모리 누수는 결코 눈에 띄지 않을 것이다.프로그램이 매우 오래 실행되지 않고 소량의 메모리만 사용하기 때문에 프로그램 존재 시 유출은 작아지고 해방될 것이다.

반면 수백만 개의 레코드를 처리해 장시간 운영하는 프로그램이 있다면, 작은 메모리 누수가 충분한 시간을 준다면 기계가 다운될 수도 있다.

누수가 있는 제3자 도서관의 경우, 문제가 발생하면 도서관을 고치거나 더 나은 대안을 찾아야 한다.그것이 문제를 일으키지 않는다면, 정말 문제가 되는가?

우선 우리의 정의를 바로 잡읍시다.메모리 누수는 메모리가 동적으로 할당될 때(예:malloc(), 그리고 메모리에 대한 모든 참조는 해당 자유 없이 손실된다.쉽게 만들 수 있는 방법은 다음과 같다.

#define BLK ((size_t)1024)
while(1){
    void * vp = malloc(BLK);
}

그 동안 (1) 루프를 돌 때마다 1024(+오버헤드) 바이트가 할당되고 vp에 새 주소가 할당되며, 이전 malloc's 블록에 대한 포인터가 남아 있지 않다는 점에 유의하십시오.이 프로그램은 힙이 다 떨어질 때까지 실행이 보장되며, 말로크의 메모리를 복구할 방법이 없다.기억은 더미에서 "떨어진다"고, 다시는 볼 수 없다.

하지만 네가 말하는 건

int main(){
    void * vp = malloc(LOTS);
    // Go do something useful
    return 0;
}

메모리를 할당하고 프로그램이 종료될 때까지 작업하십시오.이것은 메모리 누수가 아니다; 그것은 프로그램을 손상시키지 않으며, 프로그램이 종료되면 모든 메모리가 자동으로 스캔될 것이다.

일반적으로 메모리 누수는 피해야 한다.첫째, 당신 위의 고도처럼 격납고에서 다시 연료를 주입하는 것처럼 누출되어 복구되지 못하는 기억은 무용지물이고, 둘째, 메모리 누출을 방지하는 것이 나중에 메모리 누출을 발견하는 것보다 처음부터 정확하게 코딩하는 것이 훨씬 쉽기 때문이다.

아니, OS에서 정리할 수 있는 누수가 없어야 해.그 이유(내가 확인할 수 있는 한 위의 답변에서 언급되지 않음)는 당신의 메인()이 언제 다른 프로그램에서 기능/모듈로 다시 사용될지 전혀 모르기 때문이다.만약 당신의 메인()이 다른 사람의 소프트웨어에서 자주 불리는 기능이 된다면, 이 소프트웨어는 시간이 지남에 따라 메모리를 잠식하는 메모리 누수를 갖게 될 것이다.

KIV

많은 사람들은 일단 메모리를 확보하면, 그것은 즉시 운영체제로 돌아가 다른 프로그램에서 사용할 수 있다는 인상을 받고 있는 것 같다.

이건 사실이 아니에요.운영 체제는 일반적으로 4KiB 페이지의 메모리를 관리한다. malloc그리고 다른 종류의 메모리 관리는 OS에서 페이지를 가져와서 그들이 적합하다고 생각하는 대로 하위 관리한다.아마 그럴 것이다.free()당신의 프로그램이 나중에 더 많은 메모리를 저장한다는 가정 하에, 운영체제로 페이지를 반환하지 않을 것이다.

난 그렇게 말하는 게 아니야.free()메모리를 운영 체제에 반환하지 마십시오.그것은 특히 당신이 큰 기억의 확장을 자유롭게 할 때 일어날 수 있다.하지만 아무것도 장담할 수 있는 것은 없습니다.

중요한 사실:더 이상 필요 없는 메모리를 확보하지 않으면, 더 많은 메모리를 소비할 수 있는 멀록이 보장된다.하지만 당신이 먼저 자유로워진다면, 말록은 대신 자유로워진 기억을 다시 사용할지도 모른다.

이것이 실제로 의미하는 바는 무엇인가?그것은 만약 당신이 당신의 프로그램이 지금부터 더 이상의 메모리를 요구하지 않을 것이라는 것을 안다면(예를 들어, 그것은 정리 단계에 있다), 메모리를 자유롭게 하는 것은 그리 중요하지 않다는 것을 의미한다.그러나 프로그램이 나중에 더 많은 메모리를 할당할 수 있다면 메모리 누수, 특히 반복적으로 발생할 수 있는 메모리 누수는 피해야 한다.

종료 직전에 메모리를 비우는 것이 좋지 않은 이유에 대한 자세한 내용은 이 설명을 참조하십시오.

코멘터는 그 전화를 이해하지 못하는 것 같았다.free()다른 프로그램이 자동으로 사용 가능한 메모리를 사용하도록 허용하지 않는다.하지만 그게 이 답의 전부야!

그래서, 사람들을 납득시키기 위해, 나는 자유()가 별로 도움이 되지 않는 예를 보여줄 것이다.수학이 쉽게 따라올 수 있도록 OS가 4000바이트 페이지의 메모리를 관리하는 척 할 것이다.

10,000개의 100바이트 블록을 할당한다고 가정합시다(간편하게 하려면 이러한 할당을 관리하는 데 필요한 추가 메모리를 무시한다).이것은 1MB 또는 250페이지를 소모한다.만약 당신이 이 블록들 중 9000개를 임의로 풀어준다면, 당신은 단지 1000개의 블록을 남겨두게 될 것이다. 하지만 그것들은 사방에 흩어져 있다.통계적으로 약 5페이지가 비어 있을 것이다.나머지 245개 블록에는 각각 적어도 하나의 할당된 블록이 있을 것이다.이는 현재 100KB만 할당되었더라도 운영 체제에서 회수할 수 없는 980KB의 메모리에 해당된다.

한편, 당신은 지금 당신의 프로그램이 묶고 있는 메모리 양을 늘리지 않고 9000개의 블록을 더 만들 수 있다.

할 때도free()OS에 메모리를 돌려줄 수도 있지만, 그렇게 하지 않을 수도 있다. free()빠른 작동과 메모리 절약 사이에서 균형을 이루어야 한다.그리고 게다가 이미 많은 메모리를 할당했다가 해방시킨 프로그램은 다시 그렇게 될 것 같다.웹 서버는 요청 후 요청을 처리해야 한다. 즉, OS에 항상 메모리를 요청할 필요가 없도록 "슬랙" 메모리를 사용할 수 있도록 유지하는 것이 타당하다.

나는 메모리 누수가 실제로 무엇인지에 대한 잘못된 정의를 너무 많이 보게 되어 놀랍다.구체적인 정의가 없으면 그것이 나쁜 것인지 아닌지에 대한 논의는 물거품이 될 것이다.

일부 논평자가 올바르게 지적했듯이, 메모리 누수는 프로세스에 의해 할당된 메모리가 더 이상 참조하거나 삭제할 수 없을 정도로 범위를 벗어날 때에만 발생한다.

점점 더 많은 기억을 움켜쥐고 있는 과정이 반드시 새어나오는 것은 아니다.그것이 그 기억을 참조하고 할당을 해제할 수 있는 한, 그것은 그 과정의 명시적인 통제하에 남아 있고 유출되지 않았다.그 과정은 특히 메모리가 제한된 시스템의 맥락에서 잘못 설계될 수도 있지만, 이것은 누출과 같지 않다.반대로, 32바이트 버퍼의 범위를 잃는 것은, 유출된 메모리의 양은 적지만, 여전히 누출이다.만약 당신이 이것이 대수롭지 않다고 생각한다면, 누군가가 당신의 도서관 전화를 알고리즘으로 감싸서 그것을 10,000번 부를 때까지 기다리세요.

아무리 작아도 당신 자신의 코드에서 누수를 허용할 이유가 전혀 없다고 본다.C와 C++와 같은 현대의 프로그래밍 언어는 프로그래머들이 그러한 누출을 방지하도록 돕기 위해 많은 노력을 기울이며, 특히 특정 언어 시설과 결합할 때 누설을 방지하기 위해 좋은 프로그래밍 기술을 채택하지 말라는 좋은 주장은 거의 없다.

기존 또는 제3자 코드에 대해서는 누출의 심각도에 따라 품질이나 변경 능력에 대한 통제가 매우 제한적일 수 있는 경우 누출의 영향을 줄이기 위해 정기적으로 프로세스를 다시 시작하는 등의 완화 조치를 수용하거나 취할 것을 강요할 수 있다.

기존(누수)코드를 변경하거나 교체할 수 없기 때문에 반드시 수용하게 될 수도 있다.하지만, 이것은 괜찮다고 선언하는 것과는 다르다.

이런 종류의 질문 문맥은 모든 것이다.개인적으로 나는 누수를 참을 수 없고, 내 코드에서는 누수를 고치려고 많은 노력을 하지만 누수를 고치는 것이 항상 가치가 있는 것은 아니다. 그리고 가끔 사람들이 나에게 돈을 지불할 때, 내가 누수를 고치는 것은 내 수수료의 가치가 없다고 그들에게 말했다.예를 들어보자.

나는 프로젝트를 트라이어링하고, 향수 작업을 하고, 많은 버그를 고치고 있었다.응용 프로그램 초기화 중에 추적하여 완전히 이해한 누출이 있었다.제대로 고치는 것은 하루 정도 다른 기능 코드의 일부를 리팩터링하는 것이 필요했을 것이다.나는 뭔가 진부한 일을 할 수도 있었지만(예를 들어 가치를 글로벌에 주입하고 그것을 어느 정도 움켜쥐는 것은 더 이상 자유롭지 않다는 것을 알고 있다) 그것은 코드를 만져야 하는 다음 사람에게 더 많은 혼란을 야기했을 것이다.

개인적으로 나는 애초에 코드를 그런 식으로 쓰지 않았을 것이다. 하지만 우리 대부분은 항상 자연 그대로 잘 설계된 코드베이스를 작업하지는 못한다. 그리고 가끔은 이런 것들을 실용적으로 보아야 한다.150바이트의 유출이 대신 알고리즘 개선을 통해 메가바이트의 램을 줄일 수 있다는 것을 고치는데 얼마나 많은 시간이 걸렸을까.

궁극적으로는 램 1기가량을 중심으로 사용하다가 전용 기계로 달리는 앱의 150바이트를 유출하는 것은 고칠 가치가 없다고 판단해 유출된 것이며, 고치기 위해서는 무엇을 바꿔야 하는지, 그 당시에는 왜 가치가 없는 것인지 등의 댓글을 달았다.

비록 여러분이 '알려진' 기억력 유출이 대혼란을 일으키지 않을 것이라고 확신하더라도, 그렇게 하지 마십시오.기껏해야, 그것은 당신이 유사하고 아마도 더 중요한 실수를 다른 시간과 장소에서 할 수 있는 길을 만들어 줄 것이다.

나에게 이런 질문을 하는 것은 "아무도 없는 새벽 3시에 빨간불을 깰 수 있을까"라는 질문과도 같다.물론, 그것은 그 당시에 어떤 문제도 일으키지 않을 수도 있지만, 그것은 여러분이 러시아워에 같은 일을 할 수 있는 지렛대를 제공할 것이다!

나는 vfilby에 동의한다 – 그것은 달려있다.윈도에서는 메모리 누수를 비교적 톱니 모양의 벌레로 취급한다.그러나, 그것은 그 구성 요소에 따라 매우 많이 달라진다.

예를 들어, 메모리 누수는 드물게 실행되는 구성 요소의 경우, 그리고 제한된 시간 동안 그리 심각하지 않다.이 부품들은 작동하고, 비상 작업을 한 다음, 종료한다.그들이 모든 기억에서 벗어나면 암묵적으로 자유로워진다.

그러나 서비스나 기타 장기적 요소(껍질 등)에서의 메모리 누수는 매우 심각하다.그 이유는 이러한 벌레들이 시간이 지남에 따라 기억을 '스틸'하기 때문이다.이를 복구하는 유일한 방법은 구성 요소를 다시 시작하는 것이다.대부분의 사람들은 서비스나 셸을 다시 시작하는 방법을 모르기 때문에 시스템 성능이 저하되면 다시 부팅만 한다.

따라서 누출이 있는 경우 두 가지 방법으로 영향을 평가하십시오.

  1. 소프트웨어 및 사용자 경험에 적용.
  2. 시스템 자원을 절약한다는 관점에서 시스템(및 사용자)에 대해.
  3. 고정 장치가 유지 보수 및 신뢰성에 미치는 영향
  4. 다른 곳에서 회귀 분석을 유발할 가능성.

포데커

그렇다 기억의 유출은 두 가지 해악 중 더 작은 것이 될 수 있다.정확성도 중요하지만 전체 메모리 릴리즈를 수행할 때 시스템의 성능이나 안정성에 영향을 미칠 수 있으며, 메모리를 확보하고 객체를 파괴하는 데 소요되는 위험과 시간이 단순히 프로세스를 종료하는 것보다 덜 바람직할 수 있다.

일반적으로 기억을 남기는 것은 일반적으로 받아들여지지 않는다.당신의 코드가 실행될 모든 범위를 이해하기 어렵고, 경우에 따라 유출이 재앙이 될 수도 있다.

일부 메모리를 할당하고 응용 프로그램의 마지막 코드 행(예: 전역 개체의 소멸자)까지 사용하면 어떻게 하시겠습니까?

이 경우, 당신의 코드는 더 큰 프로젝트에 포팅될 수 있다.즉, 대상의 수명이 너무 길거나(대상물이 필요한 경우뿐만 아니라 프로그램 전체에서 지속된다) 글로벌이 생성되고 파괴되면 유출될 수 있다는 것을 의미할 수 있다.

애플리케이션이 종료될 때 OS를 신뢰하여 메모리를 확보해도 괜찮으십니까?

짧은 시간 동안 프로그램이 큰 것을 만들 때C++수집품(예:std::map)), 개체당 최소 2개의 할당이 있다.이 컬렉션을 반복하여 객체를 파괴하는 것은 CPU에 실시간 시간이 소요되며 객체가 누출되어 OS에 의해 정리되는 것은 성능상의 이점이 있다.카운터는 OS에 의해 정리되지 않은 리소스(예: 공유 메모리)가 있는가? 그리고 코드의 모든 개체를 파괴하지 않으면 일부는 이러한 자유롭지 못한 리소스를 보유할 위험이 있다.

만약 제3의 도서관이 당신에게 이 상황을 강요했다면?

먼저 나는 벌레 한 마리를 기르겠다.close자원들을 해방시킨 기능들.그것이 받아들여질 수 있는지에 대한 질문은 도서관이 제공하는 장점(비용, 성능, 신뢰성)이 다른 도서관과 함께 하는 것보다 나은지, 아니면 직접 쓰는 것보다 나은지에 근거한다.

일반적으로 도서관이 재초기화되지 않는 한, 나는 아마 걱정하지 않을 것이다.

보고된 누출 메모리를 가질 수 있는 허용 시간

  1. 종료 중 서비스.여기 시간 성과와 정확성 사이에 트레이드오프가 있다.
  2. 파괴될 수 없는 부서진 물체.고장난 물체(예: 예외적으로 잡힌 것 때문에)를 감지할 수 있었고, 그 물체를 파괴하려고 하면 그 결과가 행(홀드 잠금)이다.
  3. 메모리 체커가 잘못 보고됨.

종료 중 서비스

운영체제가 꺼지려고 하면 모든 자원이 정리된다.정상적인 프로세스 셧다운을 수행하지 않는 이점은 사용자가 끌 때 더 빠른 성능을 얻을 수 있다는 것이다.

깨진 물체

내 과거 속에서, 우리는 어떤 물체를 발견했다. (그리고 그 팀의 결함을 제기했는데), 만약 그들이 특정 지점에서 충돌하면, 그들은 부서지게 되고, 그 물체의 후속적인 기능들은 모두 중단되는 결과를 초래한다.

메모리 누수를 무시하는 것은 서투른 관행이지만, 교수형을 초래하는 것보다 사물과 메모리를 누설하면서 우리의 프로세스를 중단시키는 것이 더 생산적이었다.

누출 검사기 오식

일부 누출 점검기는 물체를 계측하여 작동하며, 글로브와 같은 방식으로 작동한다.그들은 때때로 다른 세계적인 물체가 유효한 파괴자를 가지고 있다는 것을 놓칠 수 있는데, 이 파괴자는 그들이 끝나면 그 기억을 풀어줄 것이다.

여기 좋은 해답이 있어.이 질문에 다른 관점을 추가하기 위해 Windows 드라이버 환경에서 개발자는 필요할 때마다 OS에서 실행 중인 일련의 콜백을 제공한다는 점에서 메모리 누수가 허용될 뿐만 아니라 바람직한 경우를 설명하겠다.콜백 중 하나는 '셧다운' 콜백으로, 시스템이 종료/재개되기 전에 실행된다.표준 상황과 달리 메모리 릴리스가 필요하지 않을 뿐만 아니라(시스템이 잠시 후에 꺼질 예정), 심지어 중단 시간을 최대한 빨리 만들고 메모리 관리의 오버헤드를 방지하는 것조차 실망스럽다.

내 생각에 너의 상황에서는 괜찮다는 답이 될 것 같아.하지만 메모리 누수는 의식적인 결정이라는 것을 분명히 문서화할 필요가 있다.당신은 유지보수 프로그래머가 함께 와서, 기능 안에 코드를 넣고, 그것을 백만 번이라고 부르는 것을 원하지 않는다.따라서 누수가 괜찮다는 결정을 내리면 향후 프로그램에 참여해야 할 사람을 위해 (IN BIG Letters) 문서화해야 한다.

만약 이것이 제3의 도서관이라면 당신은 갇히게 될지도 모른다.그러나 확실히 이 누출이 발생한다는 것을 문서화한다.

그러나 기본적으로 메모리 누수가 512KB 버퍼와 같은 알려진 수량이라면 그것은 문제가 되지 않는다.만약 당신이 도서관에 전화할 때마다 당신의 메모리가 512KB씩 증가하여 자유롭지 않다면, 당신은 문제가 생길 수 있다.만약 당신이 그것을 문서화하고 통화 실행 횟수를 통제한다면 그것은 관리할 수 있을 것이다.하지만 512가 많지는 않지만, 512만 건이 넘는 전화는 많으므로 문서화가 정말 필요하다.

또한 운영 체제 설명서를 확인하십시오.만약 이것이 내장형 장치였다면, 종료되는 프로그램으로부터 모든 메모리를 확보하지 못하는 운영체제가 있을 수 있다.잘 모르겠어, 어쩌면 이게 사실이 아닐지도 몰라.그러나 그것은 조사할 가치가 있다.

메모리 누수가 시스템 성능에 미치는 영향을 테스트하기 위한 프로그램을 작성한다면 괜찮을 것 같다.

애플리케이션 실행 후 OS를 정리하는 것은 개념적으로 잘못된 것이 없다.

그것은 정말로 애플리케이션과 그것이 어떻게 실행될지에 달려있다.몇 주 동안 실행해야 하는 애플리케이션에서 지속적으로 발생하는 누출은 관리해야 하지만, 너무 높은 메모리 없이 결과를 계산하는 작은 도구는 문제가 되지 않아야 한다.

많은 스크립팅 언어가 주기적인 참조를 수집하지 않는 데는 이유가 있다. 그 사용 패턴은 실제 문제가 아니며 따라서 낭비된 메모리만큼 자원의 낭비가 될 것이다.

누군가 예라고 할 만한 이유를 생각해 낼 수 있을 거라고 확신하지만, 그건 내가 아닐 거야.아니라고 말하는 대신, 나는 이것이 예/아니오 질문이 되어서는 안 된다고 말할 것이다.메모리 누수를 관리하거나 억제하는 방법이 있으며, 많은 시스템이 이를 보유하고 있다.

이것을 계획하는 지구를 떠나는 장치에는 NASA 시스템이 있다.이 시스템은 메모리 누수가 전체 작동에 치명적이지 않도록 자동으로 자주 재부팅된다.봉쇄의 예일 뿐이야

먼저 인식된 메모리 누수와 실제 메모리 누수 사이에는 큰 차이가 있다는 것을 깨달아야 한다.매우 빈번한 분석 도구는 많은 청어들을 보고할 것이고, 어떤 것이 실제로 유출되지 않은 곳에 (핸들 등의 메모리나 자원)이 누출되었다고 라벨을 붙일 것이다.종종 이것은 분석 도구의 구조 때문이다.예를 들어, 특정 분석 도구는 실행 시간 객체가 해제된 것을 보지 못하기 때문에 메모리 누수로 보고할 것이다.그러나 분석 도구가 볼 수 없는 런타임의 종료 코드에서 할당이 해제된다.

그렇게 말하지만, 실제 메모리 누수가 발견하기 매우 어렵거나 고치기 매우 어려운 경우가 여전히 있을 것이다.그래서 이제 문제는 그들을 코드에 남겨두어도 괜찮을까?

이상적인 대답은 "아니, 절대로"이다.보다 실용적인 대답은 "아니오, 거의 없다"일 것이다.실생활에서 당신은 해결할 수 있는 자원과 시간이 한정되어 있고 끝없는 작업 목록을 가지고 있다.기억력 유출을 제거하는 것이 과제 중 하나일 때, 수익 감소의 법칙이 작용하는 경우가 매우 많다.일주일 안에 애플리케이션에서 전체 메모리 누수의 98%를 제거할 수 있지만 나머지 2%는 몇 개월이 걸릴 수 있다.경우에 따라서는 코드의 주요한 리팩터링 없이 애플리케이션의 아키텍처 때문에 특정 누설을 제거하는 것이 불가능할 수도 있다.나머지 2%를 없앨 때 발생하는 비용과 편익을 따져봐야 한다.

만약 그것의 의도적이고 상당한 양의 메모리가 아니라면 문제가 되지 않는다면, 그것은 정말로 누설되지 않는다. 또는 상당한 양의 메모리로 성장할 수 있다.프로그램 수명 동안 전역 할당을 정리하지 않는 것은 꽤 흔한 일이다.서버나 오래 실행되는 앱에 누출이 있는 경우 시간이 지남에 따라 증가하면 문제가 된다.

나는 아니라고 믿는다. 절대 기억의 누출을 허용하지 않는다. 그리고 내가 분명히 말하지 못한 몇 가지 이유가 있다.여기에는 훌륭한 기술적 해답이 있지만, 나는 진짜 해답은 더 많은 사회적/인간적 이유에 달려 있다고 생각한다.

(첫 번째로, 다른 사람들이 언급했듯이, 진정한 누출은 프로그램이 어떤 시점에서든 할당했던 메모리 자원의 트랙을 상실할 때라는 점에 유의하십시오.C에서는, 이런 일이 일어나면 일어난다.malloc()포인터로 이동하여 포인터로 하여금free()첫 번째).

여기서 당신의 결정의 중요한 핵심은 습관이다.포인터를 사용하는 언어로 코딩하면 포인터를 많이 사용할 겁니다.그리고 포인터는 위험하다; 그것들은 당신의 코드에 모든 종류의 심각한 문제들을 추가하는 가장 쉬운 방법이다.

코딩을 할 때, 때로는 무도회에 나가기도 하고 때로는 피곤하거나 화가 나거나 걱정되기도 한다.그런 다소 산만한 시간 동안 자동 조종 장치에서는 더 많은 코딩을 할 수 있다.오토파일럿 효과는 대규모 프로젝트에서 일회성 코드와 모듈을 구분하지 않는다. 그 기간 동안, 당신이 확립하는 습관은 당신의 코드베이스에 결국 무엇이 될 것인가이다.

그러므로 절대 기억의 누출을 허락하지 말라. 차선을 변경할 때 사각지대를 점검해야 한다는 것과 같은 이유로, 비록 현재 도로의 유일한 차일지라도 말이다.당신의 활동적인 두뇌가 산만해지는 시기에는, 좋은 습관만이 당신을 비참한 실수로부터 구해줄 수 있다.

"habit" 문제를 넘어, 포인터는 복잡하고 정신적으로 추적하기 위해 많은 두뇌 파워를 필요로 하는 경우가 많다.특히 프로그래밍을 처음 접하는 경우에는 포인터 사용에 관해서는 "물 흐리게" 하지 않는 것이 가장 좋다.

사회적 측면도 더 있다.의 적절한 사용으로malloc()그리고free()당신의 코드를 보는 사람은 누구나 안심할 것이다. 당신은 당신의 자원을 관리하고 있다.하지만 그렇지 않으면 그들은 즉시 문제를 의심할 것이다.

메모리 누수가 이런 맥락에서 아무 것도 해치지 않는다는 걸 알아냈을지도 모르지만, 당신 코드의 모든 관리자들은 그가 그 코드를 읽을 때 그의 머리 속에서 그것을 알아내야 할 것이다.사용free()당신은 그 문제를 고려할 필요조차 없앤다.

마지막으로, 프로그래밍은 한 사람과 컴퓨터가 말하는 과정을 완벽하게 이해할 수 있도록 과정의 정신적 모델을 모호하지 않은 언어로 작성하는 것이다.좋은 프로그래밍 관행의 중요한 부분은 결코 불필요한 모호성을 도입하지 않는 것이다.

스마트 프로그래밍은 유연하고 일반적이다.잘못된 프로그래밍은 모호하다.

프로그램 마지막 줄까지 메모리를 할당하고 사용한다면 그건 누수가 아니다.메모리를 할당하고 잊어버리면 메모리 양이 늘어나지 않더라도 그것이 문제다.할당되었지만 사용되지 않은 메모리는 다른 프로그램이 더 느리거나 전혀 실행되지 않게 할 수 있다.

나는 한 손에 시간이 흐르면서 본 "베니그" 누수의 수를 셀 수 있다.

그래서 대답은 매우 적격이다.

예를 들면.순환 대기열이나 디큐를 저장하기 위해 버퍼가 필요하지만 버퍼가 얼마나 커야 하는지 알 수 없고 모든 판독기의 오버헤드를 감당할 수 없는 싱글톤 자원이 있다면, 기하급수적으로 배가되는 버퍼를 할당하되 기존 버퍼를 해제하지 않으면 큐/디큐당 메모리 양이 누출될 것이다.이러한 이점은 모든 액세스 속도를 획기적으로 높이고 잠금에 대한 경합 위험을 감수하지 않음으로써 멀티프로세서 솔루션의 점증요법을 변경할 수 있다는 것이다.

나는 이 접근방식이 CPU당 작업 스틸링 디케스와 같이 매우 명확하게 고정된 계수를 가진 것들과 싱글톤을 고정하는 데 사용되는 버퍼의 정도가 훨씬 덜한 것에 대해 큰 이득을 얻는 것을 보았다./proc/self/maps루트 세트 등을 검출하는 데 사용되는 C/C++용 한스봄의 보수적인 쓰레기 수집기에 명시한다.

기술적으로 누수가 발생하지만, 이 두 경우 모두 크기가 제한되어 있고 확장 가능한 원형 작업에서 디큐를 훔치는 경우 큐에 대한 메모리 사용량이 2 증가한다는 경계 요소와 맞바꾸는 엄청난 성능의 승산이 있다.

프로그램을 시작할 때 힙을 할당하고 종료할 때 힙을 해제하지 않으면 메모리 누수가 발생하지 않는다.메모리 누수는 프로그램이 코드의 한 부분에 대해 루핑을 하고 그 코드가 힙을 할당하고 나서 그것을 자유롭게 하지 않고 그것의 "추적"을 하는 것이다.

사실, 퇴장하기 직전에 무료()나 삭제 전화를 할 필요는 없다.프로세스가 종료되면 OS에 의해 모든 메모리가 회수된다(POSIX의 경우는 확실하다).다른 OS(특히 내장형 OS)에서는 YMMV).

종료 시 메모리를 확보하지 않도록 주의할 점은 예를 들어, 프로그램을 리팩터링하여 입력을 기다리는 서비스가 되고, 프로그램이 하는 모든 작업을 수행하며, 다른 서비스 호출을 기다리기 위해 루핑을 하면, 코딩한 내용이 메모리 누수로 바뀔 수 있다는 겁니다.

나는 단 한 가지 실질적인 단점만을 볼 수 있는데, 그것은 이 양성적인 누출이 메모리 누수 감지 도구를 거짓 양성으로 나타낼 것이라는 것이다.

내가 제대로 이해했다면, 메모리( 포인터가 남아 있기 때문에 해제할 수 있음)를 명시적으로 확보하지 못하고, OS에 의존하여 프로세스 종료 시 해제할 수 있다.간단한 프로그램에 문제가 없을 수도 있지만, 코드가 라이브러리로 이동되어 24x7로 실행되는 일부 상주 데몬 프로세스의 일부가 되는 상황을 고려해 보십시오.이 데몬이 코드를 사용하여 유용한 작업을 수행해야 할 때마다 스레드를 생성한다고 말하고 매시간 수천 개의 스레드를 생성한다고 말하십시오.이 경우 실제 메모리 누수가 발생할 것이다.

불행히도, 이런 상황은 실제 삶에서 일어날 것 같지 않고, 일관된 메모리 관리 기법이 여러분의 삶을 더 쉽게 만들 수도 있다.

이것은 너무 도메인마다 다르기 때문에 대답할 가치가 거의 없다.머리를 쓰라고

  • 우주 왕복선 운영 체제: 아니, 메모리 누수 금지
  • 신속한 개발 증명 코드: 모든 메모리 누수를 고치는 것은 시간 낭비다.

그리고 중간 상황의 스펙트럼이 있다.

최악의 메모리 누수를 해결하기 위해 제품 출시를 지연시키는 데 드는 기회비용($$$$$)은 대개 "직관적이거나 전문가답지 못한" 느낌을 왜소하게 만든다.네 상사는 돈을 벌기 위해 돈을 주는 것이지, 따뜻하고 흐릿한 감정을 느끼기 위해서가 아니다.

대부분의 답변이 실제 메모리 누수에 집중되지만(그것은 결코 괜찮지 않다, 왜냐하면 그것들은 엉성한 코딩의 표시이기 때문이다) 질문의 이 부분은 나에게 더 흥미롭게 보인다.

일부 메모리를 할당하고 애플리케이션의 마지막 코드 라인(예: 글로벌 개체의 디콘스터)까지 사용하면 어떻게 하시겠습니까?시간이 지남에 따라 메모리 소비량이 증가하지 않는 한, (Windows, Mac, Linux에서) 애플리케이션이 종료될 때 OS를 신뢰하여 메모리를 확보해도 괜찮으십니까?OS에 의해 해제될 때까지 메모리가 계속 사용 중이라면 실제 메모리 누수로 간주하시겠습니까?

연결된 메모리를 사용하는 경우 프로그램이 종료되기 전에 메모리를 해제할 수 없다.무료가 프로그램 종료에 의해 이루어지든 OS에 의해서 이루어지든 상관없다.이것이 문서화되는 한, 변화가 실제 메모리 누출을 초래하지 않도록, 그리고 사진에 C++ 소멸기 또는 C 정화 기능이 없는 한.기밀이 아닌 파일은 유출된 것을 통해 밝혀질 수 있다.FILE객체, 그러나 누락된 fclose는 버퍼가 플러시되지 않도록 할 수 있다.

그래서 원래의 사례로 돌아가면, 가장 강력한 누출 감지기로 꼽히는 발그라인드가 요청해야만 그러한 누출 문제를 처리할 정도로, IMHO 그 자체는 완벽하게 괜찮다.Valgrind에서는 포인터를 미리 비워두지 않고 덮어쓰면 메모리 누수로 간주되는데, 이는 다시 발생할 가능성이 높고 힙이 끝없이 커지기 때문이다.

그렇다면, 여전히 도달할 수 있는 자유로운 메모리 블록은 없다.출구에서 그들을 모두 풀어줄 수는 있지만, 그것은 그 자체로 시간 낭비일 뿐이다.요점은 그들이 에 풀려날 수 있었는지 여부다.메모리 소비량을 줄이는 것은 어떤 경우에도 유용하다.

내 생각에 너는 네 질문에 대답한 것 같아.가장 큰 단점은 메모리 누수 감지 도구를 어떻게 간섭하느냐는 것이지만, 특정 유형의 어플리케이션에 있어서 단점은 매우 큰 단점이라고 생각한다.

나는 기존 서버 애플리케이션과 함께 일하는데, 이 애플리케이션은 완전해야 하지만 누출이 있고 글로벌 DO가 메모리 감지 툴에 방해가 된다.별 거 아니에요.

In the book "Collapse" by Jared Diamond, the author wonders about what the guy was thinking who cut down the last tree on Easter Island, the tree he would have needed in order to build a canoe to get off the island. I wonder about the day many years ago when that first global was added to our codebase. THAT was the day it should have been caught.

I see the same problem as all scenario questions like this: What happens when the program changes, and suddenly that little memory leak is being called ten million times and the end of your program is in a different place so it does matter? If it's in a library then log a bug with the library maintainers, don't put a leak into your own code.

I'll answer no.

In theory, the operating system will clean up after you if you leave a mess (now that's just rude, but since computers don't have feelings it might be acceptable). But you can't anticipate every possible situation that might occur when your program is run. Therefore (unless you are able to conduct a formal proof of some behaviour), creating memory leaks is just irresponsible and sloppy from a professional point of view.

If a third-party component leaks memory, this is a very strong argument against using it, not only because of the imminent effect but also because it shows that the programmers work sloppily and that this might also impact other metrics. Now, when considering legacy systems this is difficult (consider web browsing components: to my knowledge, they all leak memory) but it should be the norm.

Historically, it did matter on some operating systems under some edge cases. These edge cases could exist in the future.

Here's an example, on SunOS in the Sun 3 era, there was an issue if a process used exec (or more traditionally fork and then exec), the subsequent new process would inherit the same memory footprint as the parent and it could not be shrunk. If a parent process allocated 1/2 gig of memory and didn't free it before calling exec, the child process would start using that same 1/2 gig (even though it wasn't allocated). This behavior was best exhibited by SunTools (their default windowing system), which was a memory hog. Every app that it spawned was created via fork/exec and inherited SunTools footprint, quickly filling up swap space.

ReferenceURL : https://stackoverflow.com/questions/273209/are-memory-leaks-ever-ok

반응형