programing

할당된 메모리에서 free()를 사용하지 않아도 될까요?

luckcodes 2022. 8. 11. 22:10

할당된 메모리에서 free()를 사용하지 않아도 될까요?

저는 컴퓨터 공학을 공부하고 있고 전자공학 강좌가 몇 개 있어요.(이러한 코스의) 두 교수로부터, 다음의 코스의 사용을 회피할 수 있다고 들었습니다.free()기능하다malloc(),calloc()할당된 메모리 공간이 다른 메모리 할당에 다시 사용되지 않을 가능성이 높기 때문입니다.즉, 예를 들어 4바이트를 할당하고 해제하면 다시 할당되지 않을 가능성이 높은4바이트의 공간이 생깁니다.이 생깁니다.

그건 미친 짓이라고 생각해요. 메모리를 더미에 할당하는 장난감이 없는 프로그램은 있을 수 없어요.하지만 그게 왜 그렇게 중요한지 정확히 설명할 수 있는 지식은 없어요malloc()이 있어야 합니다.free().

그래서: 어떤 경우라도 이 기능을 사용하는 것이 적절할 수 있는 상황은 없습니까?malloc()사용하지 않고free()만약 그렇지 않다면 교수님께 어떻게 설명해야 할까요?

간단: 반쪽짜리 문제의 출처를 읽는 것만으로 충분합니다.malloc()/free()실행.즉, 콜의 작업을 처리하는 실제 메모리 매니저를 의미합니다.런타임 라이브러리, 가상 시스템 또는 운영 체제에 있을 수 있습니다.물론 모든 경우에 동일하게 접근할 수 있는 코드는 아니다.

인접한 구멍을 큰 구멍에 접합하여 메모리가 단편화되지 않도록 하는 것은 매우 일반적인 일입니다.보다 심각한 할당자는 이를 보장하기 위해 보다 심각한 기술을 사용합니다.

세 가지 할당 및 할당 해제를 수행하고 다음 순서로 블록을 메모리에 배치한다고 가정해 보겠습니다.

+-+-+-+
|A|B|C|
+-+-+-+

개별 할당의 크기는 중요하지 않습니다.그런 다음 첫 번째와 마지막 A와 C를 해방합니다.

+-+-+-+
| |B| |
+-+-+-+

최종적으로 B를 해방시키면 (최소한 이론상으로는) 다음과 같은 결과가 됩니다.

+-+-+-+
| | | |
+-+-+-+

이 두 가지 요소 중 하나로 분류될 수 있는 것은

+-+-+-+
|     |
+-+-+-+

즉, 조각이 남지 않은 하나의 더 큰 자유 블록입니다.

요청에 따른 참조:

  • dlmalloc 코드를 읽어보세요.저는 훨씬 더 진보되어 완전한 생산 품질을 구현하고 있습니다.
  • 임베디드 애플리케이션에서도, 프래그먼트 해제 실장을 이용할 수 있습니다.예를 들어 FreeRTOS의 코드에 대한 다음 참고 사항을 참조하십시오.

다른 답변은 이미 완벽하게 잘 설명되고 있습니다.malloc()그리고.free()실제로 구멍을 더 큰 자유 덩어리로 결합합니다.하지만 그게 아니더라도 그냥 포기해버리는 건 좋지 않을 거야free().

문제는 당신의 프로그램이 그 4바이트의 메모리를 방금 할당(해제하려고 합니다)했다는 것입니다.장시간 가동할 경우 4바이트의 메모리만 다시 할당하면 될 가능성이 높습니다.따라서 이들 4바이트가 더 큰 연속된 공간으로 병합되지 않더라도 프로그램 자체에 의해 다시 사용될 수 있습니다.

전혀 말도 안 되는 소리입니다. 예를 들어, 많은 다른 구현이 있습니다.mallocDoug Lea나 처럼 더 효율적인 힙을 만들려고 하는 사람도 있습니다.

혹시 교수님들도 POSIX와 함께 일하고 계신가요?작고 최소한의 셸 어플리케이션을 많이 작성하는 데 익숙하다면 이 접근방식은 나쁘지 않을 것입니다.OS의 여유시간에 힙 전체를 해방하는 것이 1,000개의 변수를 해방하는 것보다 빠릅니다.애플리케이션이 1~2초 정도 실행될 것으로 예상되면 할당 해제 없이 쉽게 빠져나갈 수 있습니다.

물론 이것은 여전히 나쁜 관행이다(성능 향상은 항상 막연한 직감이 아니라 프로파일링에 기초해야 한다). 다른 제약을 설명하지 않고 학생들에게 말해야 할 것은 아니지만, 나는 많은 작은 피핑 셸 어플리케이션들이 이렇게 쓰여지는 것을 상상할 수 있다(정적인 할당을 완전히 사용하지 않는다면).변수를 해방하지 않음으로써 이점을 얻을 수 있는 작업을 하고 있는 경우, 매우 낮은 레이텐시 조건(이 경우 동적 할당 및 C++? :D)에서 작업하고 있거나, 매우 잘못된 작업(예를 들어 1,000개의 정수를 차례로 할당하는 것이 아니라 정수 어레이를 할당하는 것)을 하고 있는 경우입니다.n 단일 메모리 블록).

전자공학 교수라고 하셨잖아요펌웨어/실시간 소프트웨어 작성에 익숙할 수 있으며, 실행이 필요한 시간을 정확하게 측정할 수 있습니다.이 경우 모든 할당에 충분한 메모리가 있다는 것을 알고 메모리를 확보하거나 재할당하지 않으면 실행 시간이 더 쉽게 계산될 수 있습니다.

In some schemes hardware memory protection may also be used to make sure the routine completes in its allocated memory or generates a trap in what should be very exceptional cases.

Taking this from a different angle than previous commenters and answers, one possibility is that your professors have had experience with systems where memory was allocated statically(ie: when the program was compiled).

Static allocation comes when you do things like:

define MAX_SIZE 32
int array[MAX_SIZE];

In many real-time and embedded systems(those most likely to be encountered by EEs or CEs), it is usually preferable to avoid dynamic memory allocation altogether. So, uses of malloc, new, and their deletion counterparts are rare. On top of that, memory in computers has exploded in recent years.

If you have 512 MB available to you, and you statically allocate 1 MB, you have roughly 511 MB to trundle through before your software explodes(well, not exactly...but go with me here). Assuming you have 511 MB to abuse, if you malloc 4 bytes every second without freeing them, you will be able to run for nearly 73 hours before you run out of memory. Considering many machines shut off once a day, that means your program will never run out of memory!

In the above example, the leak is 4 bytes per second, or 240 bytes/min. Now imagine that you lower that byte/min ratio. The lower that ratio, the longer your program can run without problems. If your mallocs are infrequent, that is a real possibility.

Heck, if you know you're only going to malloc something once, and that malloc will never be hit again, then it's a lot like static allocation, though you don't need to know the size of what it is you're allocating up-front. Eg: Let's say we have 512 MB again. We need to malloc 32 arrays of integers. These are typical integers - 4 bytes each. We know the sizes of these arrays will never exceed 1024 integers. No other memory allocations occur in our program. Do we have enough memory? 32 * 1024 * 4 = 131,072. 128 KB - so yes. We have plenty of space. If we know we will never allocate any more memory, we can safely malloc어레이를 해방시키지 않고 사용할 수 있습니다.다만, 프로그램이 크래쉬 했을 경우는, 머신/디바이스를 재기동할 필요가 있는 경우도 있습니다.프로그램을 4,096회 시작/중지하면 512MB가 모두 할당됩니다.좀비 프로세스가 있는 경우 크래시 후에도 메모리가 해방되지 않을 수 있습니다.

고통과 불행을 피하고 이 주문을 하나의 진실로서 받아들여라.malloc항상 에 관련지을 필요가 있다free.new항상 가 있어야 한다delete.

질문에 기재되어 있는 주장은 문자 그대로 프로그래머의 입장에서 보면 말도 안 된다고 생각합니다만, OS의 관점에서는 (적어도) 진실이 있습니다.

malloc()는 최종적으로 mmap() 또는 sbrk() 중 하나를 호출하여 OS에서 페이지를 가져옵니다.

중요하지 않은 프로그램에서는 할당된 메모리의 대부분을 해방()하더라도 프로세스 수명 동안 이 페이지가 OS에 반환될 가능성은 매우 낮습니다.따라서 free()'d 메모리는 대부분의 경우 동일한 프로세스에서만 사용할 수 있으며 다른 프로세스에서는 사용할 수 없습니다.

교수님이 틀리신 게 아니라 틀리신 겁니다(적어도 오해를 일으키거나 지나치게 단순하게 만들고 있어요).메모리 플래그멘테이션은 메모리의 퍼포먼스와 효율적인 사용의 문제를 일으키기 때문에 경우에 따라서는 그것을 고려하여 회피할 필요가 있습니다.한 가지 일반적인 방법은 같은 크기의 많은 것을 할당하는 경우 부팅 시 메모리 풀을 몇 배 확보하여 내부에서 메모리 사용률을 관리하는 것입니다.이것에 의해, OS레벨에서 fragment화가 발생하지 않게 됩니다(또, 내장 메모리 매퍼의 구멍은, 이 사이즈에 딱 맞는 사이즈입니다.그 타입의 다음 오브젝트)를 참조해 주세요.

서드파티 라이브러리는 모두 이러한 처리밖에 할 수 없습니다.또한 허용 가능한 퍼포먼스와 너무 느린 동작의 차이도 있습니다. malloc()그리고.free()실행하는 데 상당한 시간이 걸리기 때문에 전화를 많이 하면 알아차릴 수 있습니다.

그래서 순진하게 사용하는 것을 피함으로써malloc()그리고.free()플래그멘테이션과 퍼포먼스 문제를 회피할 수 있습니다.단, 그 문제를 바로 해결할 때는 항상 이 문제를 회피할 필요가 있습니다.free()너의 모든 것malloc()특별한 이유가 없다면 말이죠내장 메모리 풀을 사용하고 있는 경우에서도, 뛰어난 애플리케이션을 사용하면,free()풀 메모리가 종료되기 전에 풀 메모리.네, OS가 정리합니다만, 나중에 애플리케이션의 라이프 사이클이 변경되면, 풀이 아직 남아 있는 것을 잊기 쉬워집니다.

물론 장기 실행 중인 애플리케이션에서는 할당된 모든 데이터를 청소하거나 재활용하는 데 매우 신중해야 합니다. 그렇지 않으면 메모리가 부족해집니다.

교수님들께서 중요한 점을 제기하고 계십니다.유감스럽게도 영어 사용법이 너무 많아서 뭐라고 하는지 잘 모르겠어요.특정 메모리 사용 특성이 있고 개인적으로 작업한 적이 있는 장난감이 아닌 프로그램의 관점에서 질문에 답하겠습니다.

정상적으로 동작하는 프로그램도 있습니다.메모리는 웨이브로 할당됩니다.소규모 또는 중규모의 할당이 많으면 빈 용량이 많아지고 반복 사이클이 반복됩니다.이러한 프로그램에서는, 일반적인 메모리 할당이 꽤 잘 됩니다.이들은 해방된 블록을 결합하고 파형이 끝날 때 대부분의 빈 메모리는 큰 연속된 청크로 구성됩니다.이 프로그램들은 꽤 희귀하다.

대부분의 프로그램이 제대로 작동하지 않습니다.메모리는 매우 작은 크기부터 매우 큰 크기까지 랜덤하게 할당 및 할당 해제되며 할당된 블록의 사용률이 높아집니다.이러한 프로그램에서는 블록을 병합할 수 있는 기능이 제한되고 시간이 지남에 따라 메모리가 고도로 단편화되어 비교적 연속적이지 않게 됩니다.총 메모리 사용량이 약 1.5를 초과하는 경우32비트 메모리 공간에 GB가 있으며, 10MB 이상의 할당이 있습니다.결국 대규모 할당 중 하나가 실패합니다.이러한 프로그램은 일반적입니다.

다른 프로그램은 정지할 때까지 메모리를 거의 또는 전혀 비우지 않습니다.실행 중에 메모리를 점진적으로 할당하고 소량의 메모리만 해방시킨 후 정지합니다.이 때 모든 메모리가 해방됩니다.컴파일러는 이렇습니다.VM도 마찬가지입니다.예를 들어, 입니다.NET CLR 런타임은 C++로 작성되어 있기 때문에 메모리를 해방할 수 없습니다.왜 그래야 하죠?

그리고 그것이 최종적인 답이다.프로그램의 메모리 사용량이 많은 경우 malloc 및 free를 사용하여 메모리를 관리하는 것은 이 문제에 대한 충분한 해답이 되지 않습니다.정상적으로 동작하는 프로그램을 취급할 수 있는 운이 좋은 경우를 제외하고, 1개 이상의 커스텀 메모리 할당기를 설계해, 큰 메모리 덩어리를 사전에 할당하고 나서, 선택한 전략에 따라서 서브 할당을 실시할 필요가 있습니다.프로그램이 정지된 경우를 제외하고는 무료로 사용할 수 없습니다.

Without knowing exactly what your professors said, for truly production scale programs I would probably come out on their side.

EDIT

I'll have one go at answering some of the criticisms. Obviously SO is not a good place for posts of this kind. Just to be clear: I have around 30 years experience writing this kind of software, including a couple of compilers. I have no academic references, just my own bruises. I can't help feeling the criticisms come from people with far narrower and shorter experience.

I'll repeat my key message: balancing malloc and free is not a sufficient solution to large scale memory allocation in real programs. Block coalescing is normal, and buys time, but it's not enough. You need serious, clever memory allocators, which tend to grab memory in chunks (using malloc or whatever) and free rarely. This is probably the message OP's professors had in mind, which he misunderstood.

I'm surprised that nobody had quoted The Book yet:

This may not be true eventually, because memories may get large enough so that it would be impossible to run out of free memory in the lifetime of the computer. For example, there are about 3 ⋅ 1013 microseconds in a year, so if we were to cons once per microsecond we would need about 1015 cells of memory to build a machine that could operate for 30 years without running out of memory. That much memory seems absurdly large by today’s standards, but it is not physically impossible. On the other hand, processors are getting faster and a future computer may have large numbers of processors operating in parallel on a single memory, so it may be possible to use up memory much faster than we have postulated.

http://sarabander.github.io/sicp/html/5_002e3.xhtml#FOOT298

So, indeed, many programs can do just fine without ever bothering to free any memory.

I know about one case when explicitly freeing memory is worse than useless. That is, when you need all your data until the end of process lifetime. In other words, when freeing them is only possible right before program termination. Since any modern OS takes care freeing memory when a program dies, calling free() is not necessary in that case. In fact, it may slow down program termination, since it may need to access several pages in memory.

ReferenceURL : https://stackoverflow.com/questions/22481134/is-it-ever-ok-to-not-use-free-on-allocated-memory