문제

C에서는 기억을 관리하는 방법을 실제로 지켜봐야한다고 항상 들었습니다.그리고 저는 아직 C를 배우기 시작했지만 지금까지 관련 활동을 관리하는 기억을 전혀 할 필요가 없었습니다. 저는 항상 변수를 해제하고 모든 종류의 추악한 일을해야한다고 상상했습니다.그러나 이것은 사실이 아닌 것 같습니다.

누군가가 "메모리 관리"를해야 할 때의 예를 (코드 예제와 함께) 보여줄 수 있습니까?

도움이 되었습니까?

해결책

변수를 메모리에 넣을 수있는 두 곳이 있습니다. 다음과 같은 변수를 만들 때 : 라코 디스

변수는 " 스택 "에 생성됩니다. 스택 변수는 범위를 벗어나면 (즉, 코드가 더 이상 도달 할 수없는 경우) 자동으로 해제됩니다. "자동"변수라고하는 소리를들을 수 있지만 유행에서 벗어났습니다.

많은 초보자 예제에서 스택 변수 만 사용합니다.

스택은 자동이기 때문에 좋지만 두 가지 단점도 있습니다. (1) 컴파일러는 변수의 크기를 미리 알아야하고 (b) 스택 공간이 다소 제한되어 있습니다. 예 : Windows에서 Microsoft 링커의 기본 설정에서 스택은 1MB로 설정되어 있으며 모든 변수를 변수에 사용할 수있는 것은 아닙니다.

컴파일시 배열의 크기를 모르거나 큰 배열 또는 구조체가 필요한 경우 "플랜 B"가 필요합니다.

계획 B를 ''이라고합니다. 일반적으로 운영 체제에서 허용하는만큼 큰 변수를 만들 수 있지만 직접 수행해야합니다. 이전 게시물은 다른 방법이 있지만 할 수있는 한 가지 방법을 보여주었습니다. 라코 디스

(힙의 변수는 직접 조작되지 않고 포인터를 통해 조작됩니다.)

한번 힙 변수를 생성하면 문제는 컴파일러가 작업이 끝났음을 알 수 없기 때문에 자동 해제 기능을 잃게된다는 것입니다. 그것이 당신이 언급 한 "수동 해제"가 들어오는 곳입니다. 이제 여러분의 코드는 변수가 더 이상 필요하지 않은시기를 결정하고 다른 목적으로 메모리를 사용할 수 있도록 해제 할 책임이 있습니다. 위의 경우 : 라코 디스

이 두 번째 옵션을 "불쾌한 비즈니스"로 만드는 이유는 변수가 더 이상 필요하지 않은시기를 항상 쉽게 알 수 없다는 것입니다. 필요하지 않을 때 변수를 해제하는 것을 잊으면 프로그램이 필요한만큼 더 많은 메모리를 소비하게됩니다. 이 상황을 "누수"라고합니다. "누수 된"메모리는 프로그램이 종료되고 OS가 모든 리소스를 복구 할 때까지 아무것도 사용할 수 없습니다. 실제로 작업이 완료되기 전에 실수로 힙 변수를 해제하면 더 어려운 문제도 발생할 수 있습니다.

C 및 C ++에서는 위와 같이 힙 변수를 정리해야합니다. 그러나 다른 접근 방식을 사용하는 Java 및 .NET 언어와 같은 언어 및 환경이 있으며 힙이 자체적으로 정리됩니다. "가비지 수집"이라고하는이 두 번째 방법은 개발자에게 훨씬 더 쉽지만 오버 헤드와 성능에 대한 패널티를 지불합니다. 균형입니다.

(더 간단하지만보다 수준 높은 답변을 제공하기 위해 많은 세부 정보를 살펴 보았습니다.)

다른 팁

다음은 예입니다.문자열을 복제하는 strdup () 함수가 있다고 가정합니다. 라코 디스

다음과 같이 부릅니다. 라코 디스

프로그램이 작동하는 것을 볼 수 있지만 메모리를 해제하지 않고 malloc을 통해 메모리를 할당했습니다.strdup을 두 번째로 호출했을 때 첫 번째 메모리 블록에 대한 포인터를 잃었습니다.

이 적은 양의 메모리에 대해 큰 문제는 아니지만 다음과 같은 경우를 고려하십시오. 라코 디스

이제 11 기가 바이트의 메모리를 사용했으며 (메모리 관리자에 따라 더 많을 수 있음) 충돌하지 않은 경우 프로세스가 매우 느리게 실행될 수 있습니다.

수정하려면 malloc () 사용을 마친 후 얻은 모든 것에 대해 free ()를 호출해야합니다. 라코 디스

이 예제가 도움이되기를 바랍니다.

스택이 아닌 힙의 메모리를 사용하려면 "메모리 관리"를 수행해야합니다.런타임까지 배열을 만들 크기를 모르는 경우 힙을 사용해야합니다.예를 들어 문자열에 무언가를 저장하고 싶지만 프로그램이 실행될 때까지 내용이 얼마나 큰지 알 수 없습니다.이 경우 다음과 같이 작성합니다. 라코 디스

C에서 포인터의 역할을 고려하기 위해의 질문에 답하는 가장 간결한 방법이 아닐까요?

C에서 포인터가 자신이 소유 한 메모리를 가리 키도록하는 책임은 본인과 본인의 것입니다. 이것은 효과적인 C를 작성하기 어렵게 만드는 포인터를 포기하지 않는 한 체계적이고 체계적인 접근을 필요로합니다.

현재까지 게시 된 답변은 자동 (스택) 및 힙 변수 할당에 중점을 둡니다. 스택 할당을 사용하면 자동으로 관리되고 편리한 메모리가 생성되지만 일부 상황 (대용량 버퍼, 재귀 알고리즘)에서는 스택 오버 플로라는 끔찍한 문제로 이어질 수 있습니다. 스택에 할당 할 수있는 메모리 양을 정확히 아는 것은 시스템에 따라 크게 달라집니다. 일부 임베디드 시나리오에서는 수십 바이트가 제한 일 수 있으며 일부 데스크탑 시나리오에서는 안전하게 메가 바이트를 사용할 수 있습니다.

힙 할당은 언어에 덜 내재되어 있습니다. 기본적으로 반환 ( 'free') 할 준비가 될 때까지 주어진 크기의 메모리 블록에 대한 소유권을 부여하는 라이브러리 호출 집합입니다. 간단하게 들리지만 프로그래머의 비통함과 관련이 있습니다. 문제는 간단하지만 (동일한 메모리를 두 번 해제하거나 전혀 [메모리 누수], 충분한 메모리를 할당하지 않음 [버퍼 오버플로] 등) 피하고 디버깅하기 어렵습니다. 고도로 훈련 된 접근 방식은 실제적으로 절대적으로 필수이지만 물론 언어가 실제로 그것을 요구하지는 않습니다.

다른 게시물에서 무시한 또 다른 유형의 메모리 할당을 언급하고 싶습니다. 함수 외부에서 변수를 선언하여 변수를 정적으로 할당 할 수 있습니다. 일반적으로 이러한 유형의 할당은 전역 변수에서 사용되기 때문에 나쁜 평가를받는다고 생각합니다. 그러나 이런 방식으로 할당 된 메모리를 사용하는 유일한 방법은 스파게티 코드의 엉망진창에서 규율이없는 전역 변수를 사용하는 것이라고 말하는 것은 없습니다. 정적 할당 방법은 힙 및 자동 할당 방법의 일부 함정을 피하기 위해 간단히 사용할 수 있습니다. 일부 C 프로그래머는 크고 정교한 C 임베디드 및 게임 프로그램이 힙 할당을 전혀 사용하지 않고 구성되었다는 사실에 놀랐습니다.

여기에 메모리를 할당하고 해제하는 방법에 대한 몇 가지 훌륭한 답변이 있습니다. 제 생각에 C 사용의 더 어려운 측면은 사용하는 메모리가 할당 된 메모리뿐인지 확인하는 것입니다. 이것이 올바르게 수행되지 않은 경우 결국이 사이트의 사촌 (버퍼 오버 플로우)이 발생하고 다른 애플리케이션에서 사용중인 메모리를 덮어 쓰고 매우 예측할 수없는 결과를 초래할 수 있습니다.

예 : 라코 디스

이 시점에서 myString에 5 바이트를 할당하고 "abcd \ 0"(문자열은 null-\ 0으로 끝남)으로 채웠습니다. 문자열 할당이 라코 디스

프로그램에 할당 한 5 바이트에 "abcde"를 할당하고 후행 널 문자는이 끝에 놓이게됩니다. 이는 사용을 위해 할당되지 않은 메모리의 일부입니다. 무료 일 수 있지만 다른 애플리케이션에서 동일하게 사용할 수 있습니다. 이는 메모리 관리의 중요한 부분으로, 실수로 인해 예측할 수없는 (때로는 반복 할 수없는) 결과를 초래합니다.

기억해야 할 사항은 포인터를 NULL로 항상 초기화하는 것입니다. 초기화되지 않은 포인터에는 포인터 오류가 조용히 진행될 수있는 의사 난수 유효 메모리 주소가 포함될 수 있기 때문입니다.포인터가 NULL로 초기화되도록 강제하면이 포인터를 초기화하지 않고 사용하는 경우 항상 포착 할 수 있습니다.그 이유는 운영 체제가 가상 주소 0x00000000을 일반 보호 예외에 "연결"하여 널 포인터 사용을 트랩하기 때문입니다.

또한 거대한 배열을 정의해야 할 때 동적 메모리 할당을 사용할 수도 있습니다 (예 : int [10000]).스택에 넣을 수는 없습니다. 흠 ... 스택 오버플로가 발생하기 때문입니다.

또 다른 좋은 예는 연결 목록 또는 이진 트리와 같은 데이터 구조의 구현입니다.여기에 붙여 넣을 샘플 코드는 없지만 쉽게 검색 할 수 있습니다.

(지금까지의 답변이 정확하지 않다고 느끼기 때문에 글을 씁니다.)

언급 할 가치가있는 메모리 관리를해야하는 이유는 복잡한 구조를 만들어야하는 문제 / 솔루션이있을 때입니다. (한 번에 스택의 많은 공간에 할당하면 프로그램이 충돌하는 경우 버그입니다.) 일반적으로 학습해야 할 첫 번째 데이터 구조는 일종의 목록 . 여기에 링크 된 하나가 있습니다. 라코 디스

당연히 다른 몇 가지 기능이 필요하지만 기본적으로 메모리 관리가 필요합니다. "수동"메모리 관리로 가능한 많은 트릭이 있음을 지적해야합니다. 예 :

  • malloc 이 (언어 표준에 의해) 보장된다는 사실을 사용하여 포인터를 반환합니다. 4로 나눌 수 있습니다.
  • 자신의 사악한 목적을 위해 추가 공간 할당
  • 메모리 풀 을 만드는 중 ..

    좋은 디버거를 구하세요 ... 행운을 빕니다!

@ 유로 미첼 리

추가해야 할 한 가지 부정적인 점은 함수가 반환 될 때 스택에 대한 포인터가 더 이상 유효하지 않기 때문에 함수에서 스택 변수에 대한 포인터를 반환 할 수 없다는 것입니다.이것은 일반적인 오류이며 스택 변수만으로는 얻을 수없는 주된 이유입니다.함수가 포인터를 반환해야하는 경우 malloc을 수행하고 메모리 관리를 처리해야합니다.

<인용구>

@ Ted Percival :
... malloc ()의 반환 값을 캐스팅 할 필요가 없습니다.

물론 맞습니다. K & R 이 확인했습니다.

저는 C에서 암시 적 변환을 많이 좋아하지 않으므로 "마법"을 더 잘 보이게 만들기 위해 캐스트를 사용하는 경향이 있습니다. 가독성을 높이는 데 도움이되는 경우도 있고 그렇지 않은 경우도 있으며, 컴파일러가 자동 버그를 포착하는 경우도 있습니다. 그래도 나는 이것에 대해 어떤 식 으로든 강한 의견을 가지고 있지 않습니다. <인용구>

컴파일러가 C ++ 스타일 주석을 이해하는 경우 특히 그렇습니다.

예 ... 당신이 저를 잡았습니다. 저는 C보다 C ++에서 더 많은 시간을 보냅니다. 알아 주셔서 감사합니다.

C에서는 실제로 두 가지 다른 선택이 있습니다. 첫째, 시스템이 메모리를 관리하도록 할 수 있습니다. 또는 혼자서 할 수 있습니다. 일반적으로 가능한 한 오랫동안 전자를 고수하는 것이 좋습니다. 그러나 C의 자동 관리 메모리는 매우 제한적이며 다음과 같은 많은 경우 메모리를 수동으로 관리해야합니다.

a. 변수가 함수보다 오래 지속되기를 원하고 전역 변수를 원하지 않습니다. 예 : 라코 디스

b. 동적으로 할당 된 메모리를 원합니다. 가장 일반적인 예는 고정 길이가없는 배열입니다. 라코 디스

보기, 긴 값은 모든 것을 담기에 충분합니다. 그것을 해제하는 것을 기억하십시오. 그렇지 않으면 후회할 것입니다. 이것은 C : D에서 재미있게 놀기 위해 제가 가장 좋아하는 트릭 중 하나입니다.

하지만 일반적으로 좋아하는 트릭 (T___T)은 피하고 싶을 것입니다. 너무 자주 사용하면 조만간 OS가 손상됩니다. * alloc과 free를 사용하지 않는 한, 당신은 아직 처녀이고 코드가 여전히 멋져 보인다고 말하는 것이 안전합니다.

예. 범위 외부에 존재하는 객체를 생성하는 경우 사용합니다. 여기에 인위적인 예제가 있습니다 (내 구문은 꺼져 있고 C는 녹슬지 만이 예제는 여전히 개념을 설명합니다). 라코 디스

이 예에서는 MyClass의 수명 동안 SomeOtherClass 유형의 개체를 사용하고 있습니다. SomeOtherClass 객체는 여러 함수에서 사용되므로 동적으로 메모리를 할당했습니다. SomeOtherClass 객체는 MyClass가 생성 될 때 생성되고 객체 수명 동안 여러 번 사용 된 다음 MyClass가 해제되면 해제됩니다.

분명히 이것이 실제 코드라면, 이런 방식으로 myObject를 생성 할 이유 (스택 메모리 소비를 제외하고)가 없을 것입니다. 그러나 이러한 유형의 객체 생성 / 파괴는 많은 객체가 있고 원하는 경우 유용합니다. 생성 및 파괴시기를 세밀하게 제어하고 (예를 들어 애플리케이션이 전체 수명 동안 1GB의 RAM을 차지하지 않도록) Windowed 환경에서는 사용자가 생성하는 개체 (버튼 , 예를 들어) 특정 함수 (또는 클래스) 범위 밖에서 잘 존재해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top