프로세스가 중단되면 메모리 누수가 발생합니까?

프로세스가 중단되면 메모리 누수가 발생합니까?

일부 변수를 수동으로 할당하는 프로그램을 c/C++로 생성한다고 가정해 보겠습니다. 그런 다음 프로그램을 실행하는 동안 인터럽트 신호(Ctrl-C)를 보냅니다. 이러한 변수는 메모리에서 해제됩니까, 아니면 시스템이 종료될 때까지 공간을 차지합니까?

또한 수동으로 할당되지 않은 정수를 방금 생성한 경우 이러한 변수가 지속됩니까, 아니면 즉시 삭제됩니까?

할당된 변수는 그대로 유지되고 일반 변수는 (스택 때문에) 삭제될 것이라고 생각합니다. 이런 경우, 프로그램이 중지된 후 할당된 변수를 메모리에서 해제할 수 있는 방법이 있습니까?

그냥 궁금해서요. :)

답변1

프로세스는 커널에 의해 관리됩니다. 커널은 프로그래머가 변수를 할당하는 방법에 관심이 없습니다. 특정 메모리 블록이 프로세스에 속한다는 것만 알고 있습니다. C 런타임은 C 메모리 관리 기능을 커널 기능과 일치시킵니다. 자동 변수는 "스택"이라는 메모리 블록에 들어가고 동적 저장소( malloc및 친구들)는 "힙"이라는 메모리 블록에 들어갑니다. 프로세스는 다음과 같은 시스템 호출을 호출합니다.sbrk그리고mmap세분성을 다음과 같이 가져옵니다.메모리 관리 장치 페이지. 런타임은 이러한 블록 내에서 자동 변수와 동적으로 할당된 개체를 배치할 위치를 결정합니다.

프로세스가 종료되면 커널은 프로세스에서 더 이상 사용하지 않는 각 MMU 페이지를 기록하기 위해 메모리 관리 테이블을 업데이트합니다. 이는 자체 위반(시스템 호출 호출)이든 비위반(신호에 의해 종료)이든 프로세스가 종료되는 방식에 관계없이 발생합니다. 어떤 프로세스에서도 더 이상 사용되지 않는 페이지는 재사용 가능으로 표시됩니다.

장기 실행 프로그램에서 코드 조각이 언제 재사용될 수 있는지 알 수 없기 때문에 더 이상 사용되지 않는 동적으로 할당된 저장소를 해제하는 것이 일반적으로 위생상 좋습니다. 그러나 프로세스가 종료되면 운영 체제는 메모리, 열린 파일 등 모든 리소스를 해제합니다.

운영 체제에서 자동으로 정리되지 않는 유일한 리소스는 임시 파일과 같이 운영 체제에서 전역 범위를 갖도록 설계된 리소스입니다.

답변2

SIGINT시스템 호출은 프로세스가 정상적으로 종료되거나 등을 통해 종료될 때마다 호출됩니다. 이 호출 작업의 일부는 프로세스가 사용 중인 리소스를 회수하는 것입니다. 기본적으로 운영 체제에서 반환된 종료 상태(성공 또는 실패)를 확인할 때마다 두 가지 일이 발생합니다.SIGTERMSIGKILLexitexit

  1. SIGCHLD하위 프로세스가 종료되었음을 상위 프로세스에 알리기 위해 상위 프로세스로 전송됩니다.
  2. exit방금 종료된 프로세스에서 사용된 리소스를 정리하는 시스템 호출을 호출합니다.

좀비 및 고아 프로세스의 경우에도 운영 체제는 종료 코드를 캡처하기 위해 특수 프로세스를 할당한 다음 exit시스템 호출을 호출합니다.

free()그러나 이것이 코드에서 사용할 수 없다는 의미는 아닙니다 . 이렇게 하지 않으면 소프트웨어의 메모리 요구 사항이 증가하여 전체 시스템 속도가 느려집니다. 더 이상 필요하지 않은 것은 모두 출시되어야 합니다.

답변3

일부 메모리 비트를 지워야 하는 경우(예: 비밀번호 또는 개인 키) memset(3)프로세스가 시작되기 전에 호출하거나 작업을 수행하기 위한 신호 처리기가 필요합니다. 당신은 또한 볼 수 있습니다나트륨sodium_mlock, 여기 sodium_memzero에는 다음과 관련된 편리하고 이식 가능한 루틴이 있습니다. 커널은 각 프로세스가 종료된 후 항상 모든 메모리를 0으로 만들 수 있지만 이로 인해 시스템 속도가 느려질 수 있습니다.

이전에 사용된(그러나 0이 아닐 수도 있음) 메모리는 필요한 경우 커널에 의해 재사용됩니다. 수동 메모리 할당을 제공하는 언어의 프로그래머는 데이터 구조에 이전 프로그램의 내용이 포함될 수 있다는 점을 인식해야 합니다( -Wuninitialized컴파일된 The 장치 플래그는 여기와 관련이 있습니다).

모든 할당이 항상 0으로 설정된다는 StephenKitt의 주장에 대해서는 해당 가정을 기반으로 코드를 작성할 수 있을 것 같습니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
    int i, blahblah[1000000];
    for (i = 0; i < 1000000; i++) {
      if (blahblah[i] != 0) {
          printf("whoops, %d at %d ain't zero\n", blahblah[i], i);
      }
    }
    exit(EXIT_SUCCESS);
}

관련 정보