다음 C 코드가 있다고 가정 해 보겠습니다.
int main () {
int *p = malloc(10 * sizeof *p);
*p = 42;
return 0; //Exiting without freeing the allocated memory
}
C 프로그램을 컴파일하고 실행할 때, 즉 메모리에 일부 공간을 할당 한 후 응용 프로그램을 종료하고 프로세스가 종료 된 후에도 할당 한 메모리가 계속 할당됩니까 (즉, 기본적으로 공간을 차지합니까)?
답변
운영 체제에 따라 다릅니다. 대부분의 최신 (및 모든 주요) 운영 체제는 프로그램이 종료 될 때 해제되지 않은 메모리를 해제합니다.
이것에 의존하는 것은 나쁜 습관이며 명시 적으로 해제하는 것이 좋습니다. 문제는 코드가 나쁘다는 것만이 아닙니다. 작은 프로그램을 더 크고 오래 실행되는 프로그램에 통합하기로 결정할 수 있습니다. 그런 다음 잠시 후 메모리 누수를 추적하는 데 몇 시간을 소비해야합니다.
운영 체제의 기능에 의존하면 코드의 이식성이 떨어집니다.
답변
일반적으로 최신 범용 운영 체제는 프로세스가 종료 된 후 정리합니다 . 대체 방법은 시스템이 시간이 지남에 따라 리소스를 잃고 제대로 작성되지 않았거나 리소스를 누출하는 버그가 거의 발생하지 않는 프로그램으로 인해 재부팅이 필요하기 때문에 필요합니다.
어쨌든 프로그램이 리소스를 명시 적으로 해제하는 것은 다음과 같은 다양한 이유로 좋은 습관이 될 수 있습니다 .
- 임시 파일이나 외부 리소스 상태 변경 과 같이 종료시 OS에 의해 정리 되지 않는 추가 리소스가있는 경우 종료시 이러한 모든 작업을 처리하는 코드가 필요합니다. 종종 메모리 해제와 우아하게 결합됩니다.
- 프로그램의 수명이 길어지기 시작하면 메모리를 해제하는 유일한 방법이 종료되는 것을 원하지 않을 것 입니다. 예를 들어, 프로그램을 개별 작업 단위에 대한 많은 요청을 처리하는 동안 계속 실행되는 서버 (데몬)로 변환하거나 프로그램이 더 큰 프로그램의 작은 부분이 될 수 있습니다.
그러나 메모리 확보를 건너 뛰는 이유는 효율적인 종료 입니다. 예를 들어 애플리케이션에 메모리에 큰 캐시가 있다고 가정합니다. 종료 될 때 전체 캐시 구조를 통과하여 한 번에 하나씩 해제하면 유용한 목적이없고 리소스가 낭비됩니다. 특히, 캐시가 포함 된 메모리 페이지가 운영 체제에 의해 디스크로 스왑 된 경우를 고려하십시오. 구조를 살펴보고 해제 함으로써 모든 페이지를 한꺼번에 메모리로 되돌리고 실제 이익을 위해 상당한 시간과 에너지를 낭비하고 시스템의 다른 프로그램이 교체 될 수도 있습니다!
관련 예로서 각 요청에 대한 프로세스를 생성 한 다음 완료되면 종료되도록하는 고성능 서버가 있습니다. 즉 , 프로세스가 끝날 때 모든 것이 운영 체제의 사용 가능한 메모리로 다시 사라지기 때문에 메모리 할당 을 추적 할 필요도없고 해제 또는 가비지 수집을 전혀 수행하지 않습니다. (사용자 지정 메모리 할당자를 사용하여 프로세스 내에서 동일한 종류의 작업을 수행 할 수 있지만 매우 신중한 프로그래밍이 필요합니다. 본질적으로 OS 프로세스 내에서 “경량 프로세스”에 대한 자신의 개념을 만들어야합니다.)
답변
이 스레드에 마지막 게시물을 올린 후 너무 오래 게시 한 것에 대해 사과드립니다.
추가 포인트 하나. 모든 프로그램이 정상적으로 종료되는 것은 아닙니다. 충돌 및 ctrl-C 등으로 인해 프로그램이 제어되지 않은 방식으로 종료됩니다. OS가 힙을 해제하지 않고, 스택을 정리하고, 정적 변수를 삭제하는 등의 작업을 수행하지 않으면 결국 시스템이 메모리 누수로 인해 충돌하거나 더 나빠질 수 있습니다.
이 외에도 흥미롭게도 우분투에서 충돌 / 중단이 발생하고 다른 모든 최신 OS에는 “처리 된”리소스에 문제가 있다고 생각합니다. 소켓, 파일, 장치 등은 프로그램이 종료 / 충돌 될 때 “열려있는”상태로 유지 될 수 있습니다. 또한 정상 종료 전에 정리의 일부로 “핸들”또는 “설명자”로 모든 항목을 닫는 것이 좋습니다.
현재 소켓을 많이 사용하는 프로그램을 개발 중입니다. 교수형에 갇 히면 ctrl-c를 눌러 소켓을 좌초시켜야합니다. 모든 열린 소켓 목록과 sigint 및 sigterm을 포착하는 sigaction 핸들러를 수집하기 위해 std :: vector를 추가했습니다. 핸들러는 목록을 살펴보고 소켓을 닫습니다. 나는 조기 종료로 이어질 던지기 전에 사용할 유사한 정리 루틴을 만들 계획입니다.
이 디자인에 대해 언급하고 싶은 사람이 있습니까?
답변
여기서 일어나는 일은 ( 최신 OS에서 ) 프로그램이 자체 “프로세스”내에서 실행된다는 것입니다. 이것은 자체 주소 공간, 파일 설명자 등이 부여 된 운영 체제 엔터티입니다. malloc
호출은 “힙”또는 프로세스에 할당 된 할당되지 않은 메모리 페이지에서 메모리를 할당합니다.
이 예에서와 같이 프로그램이 종료되면 프로세스에 할당 된 모든 리소스가 운영 체제에 의해 재활용 / 폐기됩니다. 메모리의 경우 사용자에게 할당 된 모든 메모리 페이지는 단순히 “사용 가능”으로 표시되고 다른 프로세스에서 사용할 수 있도록 재활용됩니다. 페이지는 malloc이 처리하는 것보다 낮은 수준의 개념입니다. 결과적으로 malloc / free의 세부 사항은 모든 것이 정리됨에 따라 모두 사라집니다.
랩톱 사용을 마치고 친구에게주고 싶을 때 각 파일을 개별적으로 삭제하지 않아도되는 것과 도덕적으로 동일합니다. 하드 드라이브를 포맷하기 만하면됩니다.
이 모든 것은 다른 모든 응답자가 지적했듯이 이것에 의존하는 것은 좋은 습관이 아닙니다.
- 항상 리소스를 관리하도록 프로그래밍해야하며 C에서는 메모리도 의미합니다. 결국 라이브러리에 코드를 임베드하거나 예상보다 훨씬 오래 실행될 수 있습니다.
- 일부 OS (오래된 OS 및 일부 최신 임베디드 OS)는 이러한 하드 프로세스 경계를 유지하지 않을 수 있으며 할당은 다른 주소 공간에 영향을 미칠 수 있습니다.
답변
예. OS가 리소스를 정리합니다. 음 … NetWare의 이전 버전은 그렇지 않았습니다.
편집 : San Jacinto가 지적했듯이이를 수행하지 않는 시스템 (NetWare 제외)이 확실히 있습니다. 일회용 프로그램에서도 나는 습관을 유지하기 위해 모든 자원을 자유롭게하는 습관을들이려고 노력합니다.
답변
예, 운영 체제는 프로세스가 종료되면 모든 메모리를 해제합니다.
답변
운영 체제는 일반적으로이를 정리하지만, 예를 들어 임베디드 소프트웨어를 작업하는 경우 릴리스되지 않을 수 있습니다.
비워두면 나중에 대규모 프로젝트에 통합 할 때 많은 시간을 절약 할 수 있습니다.