Nice programing

malloc과 calloc의 차이점은 무엇입니까?

nicepro 2020. 9. 29. 18:41
반응형

malloc과 calloc의 차이점은 무엇입니까?


하는 것의 차이점은 무엇입니까?

ptr = (char **) malloc (MAXELEMS * sizeof(char *));

또는:

ptr = (char **) calloc (MAXELEMS, sizeof(char*));

calloc을 malloc보다 사용하거나 그 반대로 사용하는 것이 좋은 생각은 언제입니까?


calloc()0은 버퍼를 초기화 malloc()하고 메모리는 초기화되지 않은 상태로 둡니다.

편집하다:

메모리를 0으로 만드는 데 약간의 시간이 걸릴 수 있으므로 malloc()해당 성능이 문제인 경우 사용 하는 것이 좋습니다. 메모리 초기화가 더 중요한 경우 calloc(). 예를 들어,에 calloc()대한 호출을 저장할 수 있습니다 memset().


덜 알려진 차이점은 Linux와 같이 낙관적 인 메모리 할당을 사용하는 운영 체제에서에서 반환 된 포인터 malloc는 프로그램이 실제로 터치 할 때까지 실제 메모리에 의해 지원되지 않는다는 것입니다.

calloc실제로 메모리를 건 드리기 때문에 (0을 씁니다) 따라서 OS가 실제 RAM (또는 스왑)으로 할당을 뒷받침하는지 확인할 수 있습니다. 이것이 malloc보다 느린 이유이기도합니다 (0을 0으로 설정해야 할뿐만 아니라 OS는 다른 프로세스를 교체하여 적절한 메모리 영역을 찾아야합니다).

예를 들어 malloc의 동작에 대한 추가 토론은 이 SO 질문참조하십시오.


의 자주 간과되는 장점 중 하나 calloc는 정수 오버플로 취약성으로부터 사용자를 보호하는 데 도움이된다는 것입니다. 비교:

size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);

size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);

만약 전자는 작은 할당 이후의 버퍼 오버 플로우가 발생할 수 count보다 크다 SIZE_MAX/sizeof *bar. 큰 개체를 만들 수 없기 때문에이 경우 후자는 자동으로 실패합니다.

물론 오버플로의 가능성을 무시하는 부적합한 구현을 찾아야 할 수도 있습니다. 대상 플랫폼에서 이것이 문제가된다면 어쨌든 오버플로에 대한 수동 테스트를 수행해야합니다.


문서는 calloc을 malloc처럼 보이게하여 메모리를 0으로 초기화합니다. 이것은 주요 차이점이 아닙니다! calloc의 아이디어는 메모리 할당을위한 copy-on-write 의미 체계를 제거하는 것입니다. calloc으로 메모리를 할당하면 모두 0으로 초기화 된 동일한 물리적 페이지에 매핑됩니다. 할당 된 메모리의 페이지가 실제 페이지에 기록 될 때 할당됩니다. 예를 들어, 비어있는 해시 부분은 추가 메모리 (페이지)에 의해 지원되지 않기 때문에 이것은 종종 거대한 해시 테이블을 만드는 데 사용됩니다. 프로세스간에 공유 할 수도있는 0으로 초기화 된 단일 페이지를 기꺼이 가리 킵니다.

가상 주소에 대한 모든 쓰기는 페이지에 매핑됩니다. 해당 페이지가 제로 페이지이면 다른 물리적 페이지가 할당되고 제로 페이지가 여기에 복사되고 제어 흐름이 클라이언트 프로세스로 반환됩니다. 이것은 메모리 매핑 파일, 가상 메모리 등이 작동하는 방식과 동일하게 작동합니다. 페이징을 사용합니다.

다음은 주제에 대한 최적화 이야기입니다. http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/


할당 된 메모리 블록의 크기에는 차이가 없습니다. calloc메모리 블록을 물리적으로 모두 0 비트 패턴으로 채 웁니다. 실제로 할당 된 메모리 블록에있는 객체 calloc는 리터럴로 초기화 된 것처럼 초기 값 갖는다 고 가정합니다 0. 즉, 정수는 0, 부동 소수점 변수-값 0.0, 포인터-적절한 널 포인터 값을 가져야 합니다. , 등등.

그러나 현명한 관점에서 볼 때 calloc(뿐만 아니라 memset(..., 0, ...))은 유형의 객체를 (0으로) 올바르게 초기화하는 것만 보장됩니다 unsigned char. 다른 모든 것은 적절하게 초기화된다는 보장이 없으며 정의되지 않은 동작을 유발하는 소위 트랩 표현을 포함 할 수 있습니다 . 즉, unsigned char앞서 언급 한 모두 0 비트가 아닌 다른 유형의 경우 patterm은 잘못된 값인 트랩 표현을 나타낼 수 있습니다.

나중에 Technical Corrigenda to C99 표준 중 하나에서 모든 정수 유형에 대해 동작이 정의되었습니다 (이치에 맞음). 즉, 공식적으로 현재 C 언어에서는 calloc(및 memset(..., 0, ...))를 사용 하여 정수 유형 만 초기화 할 수 있습니다 . 일반적으로 다른 것을 초기화하는 데 사용하면 C 언어의 관점에서 정의되지 않은 동작이 발생합니다.

실제로 calloc는 우리 모두가 알고 있듯이 작동하지만 (위 내용을 고려할 때) 사용 여부는 귀하에게 달려 있습니다. 나는 개인적으로 그것을 완전히 피하고 malloc대신 사용하고 내 자신의 초기화를 수행 하는 것을 선호합니다 .

마지막으로, 또 다른 중요한 세부 사항은 요소 크기에 요소 수를 곱하여 내부적으로calloc 최종 블록 크기를 계산하는 데 필요 하다는 것 입니다 . 그렇게하는 동안 가능한 산술 오버플로를 관찰해야합니다. 요청 된 블록 크기를 올바르게 계산할 수없는 경우 할당 실패 (널 포인터)가 발생합니다. 한편, 귀하의 버전은 오버플로를 감시하지 않습니다. 오버플로가 발생하는 경우 "예측할 수없는"메모리 양을 할당합니다.callocmalloc


from an article Benchmarking fun with calloc() and zero pages on Georg Hager's Blog

When allocating memory using calloc(), the amount of memory requested is not allocated right away. Instead, all pages that belong to the memory block are connected to a single page containing all zeroes by some MMU magic (links below). If such pages are only read (which was true for arrays b, c and d in the original version of the benchmark), the data is provided from the single zero page, which – of course – fits into cache. So much for memory-bound loop kernels. If a page gets written to (no matter how), a fault occurs, the “real” page is mapped and the zero page is copied to memory. This is called copy-on-write, a well-known optimization approach (that I even have taught multiple times in my C++ lectures). After that, the zero-read trick does not work any more for that page and this is why performance was so much lower after inserting the – supposedly redundant – init loop.


calloc is generally malloc+memset to 0

It is generally slightly better to use malloc+memset explicitly, especially when you are doing something like:

ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));

That is better because sizeof(Item) is know to the compiler at compile time and the compiler will in most cases replace it with the best possible instructions to zero memory. On the other hand if memset is happening in calloc, the parameter size of the allocation is not compiled in in the calloc code and real memset is often called, which would typically contain code to do byte-by-byte fill up until long boundary, than cycle to fill up memory in sizeof(long) chunks and finally byte-by-byte fill up of the remaining space. Even if the allocator is smart enough to call some aligned_memset it will still be a generic loop.

One notable exception would be when you are doing malloc/calloc of a very large chunk of memory (some power_of_two kilobytes) in which case allocation may be done directly from kernel. As OS kernels will typically zero out all memory they give away for security reasons, smart enough calloc might just return it withoud additional zeroing. Again - if you are just allocating something you know is small, you may be better off with malloc+memset performance-wise.


Difference 1:

malloc() usually allocates the memory block and it is initialized memory segment.

calloc() allocates the memory block and initialize all the memory block to 0.

Difference 2:

If you consider malloc() syntax, it will take only 1 argument. Consider the following example below:

data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );

Ex: If you want to allocate 10 block of memory for int type,

int *ptr = (int *) malloc(sizeof(int) * 10 );

If you consider calloc() syntax, it will take 2 arguments. Consider the following example below:

data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));

Ex: if you want to allocate 10 blocks of memory for int type and Initialize all that to ZERO,

int *ptr = (int *) calloc(10, (sizeof(int)));

Similarity:

Both malloc() and calloc() will return void* by default if they are not type casted .!


There are two differences.
First, is in the number of arguments. malloc() takes a single argument (memory required in bytes), while calloc() needs two arguments.
Secondly, malloc() does not initialize the memory allocated, while calloc() initializes the allocated memory to ZERO.

  • calloc() allocates a memory area, the length will be the product of its parameters. calloc fills the memory with ZERO's and returns a pointer to first byte. If it fails to locate enough space it returns a NULL pointer.

Syntax: ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block); i.e. ptr_var=(type *)calloc(n,s);

  • malloc() allocates a single block of memory of REQUSTED SIZE and returns a pointer to first byte. If it fails to locate requsted amount of memory it returns a null pointer.

Syntax: ptr_var=(cast_type *)malloc(Size_in_bytes); The malloc() function take one argument, which is the number of bytes to allocate, while the calloc() function takes two arguments, one being the number of elements, and the other being the number of bytes to allocate for each of those elements. Also, calloc() initializes the allocated space to zeroes, while malloc() does not.


The calloc() function that is declared in the <stdlib.h> header offers a couple of advantages over the malloc() function.

  1. It allocates memory as a number of elements of a given size, and
  2. It initializes the memory that is allocated so that all bits are zero.

A difference not yet mentioned: size limit

void *malloc(size_t size) can only allocate up to SIZE_MAX.

void *calloc(size_t nmemb, size_t size); can allocate up about SIZE_MAX*SIZE_MAX.

This ability is not often used in many platforms with linear addressing. Such systems limit calloc() with nmemb * size <= SIZE_MAX.

Consider a type of 512 bytes called disk_sector and code wants to use lots of sectors. Here, code can only use up to SIZE_MAX/sizeof disk_sector sectors.

size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);

Consider the following which allows an even larger allocation.

size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);

Now if such a system can supply such a large allocation is another matter. Most today will not. Yet it has occurred for many years when SIZE_MAX was 65535. Given Moore's law, suspect this will be occurring about 2030 with certain memory models with SIZE_MAX == 4294967295 and memory pools in the 100 of GBytes.


malloc() and calloc() are functions from the C standard library that allow dynamic memory allocation, meaning that they both allow memory allocation during runtime.

Their prototypes are as follows:

void *malloc( size_t n);
void *calloc( size_t n, size_t t)

There are mainly two differences between the two:

  • Behavior: malloc() allocates a memory block, without initializing it, and reading the contents from this block will result in garbage values. calloc(), on the other hand, allocates a memory block and initializes it to zeros, and obviously reading the content of this block will result in zeros.

  • Syntax: malloc() takes 1 argument (the size to be allocated), and calloc() takes two arguments (number of blocks to be allocated and size of each block).

The return value from both is a pointer to the allocated block of memory, if successful. Otherwise, NULL will be returned indicating the memory allocation failure.

Example:

int *arr;

// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int)); 

// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));

The same functionality as calloc() can be achieved using malloc() and memset():

// allocate memory for 10 integers with garbage values   
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int)); 

Note that malloc() is preferably used over calloc() since it's faster. If zero-initializing the values is wanted, use calloc() instead.


No of blocks:
malloc() Assigns single block of demanded memory,
calloc() Assigns multiple blocks of the requested memory

Initialization:
malloc() doesn't clear and initialize the allocated memory.
calloc() initialize the allocated memory by zero.

Speed:
malloc() speed is Fast.
calloc() speed is Comparatively slow.

Syntex:

void *malloc(size_t size);                   // syntex for malloc() function
void *calloc(size_t num, size_t size);       // syntex for calloc() function

Argument:
If you consider malloc() syntax, it will take only 1 argument.
If you consider calloc() syntax, it will take 2 arguments.

Manner of memory Allocation::
malloc() function assigns memory of the desired 'size' from the available heap.
calloc() function assigns memory that is the size of what’s equal to ‘num *size’.

Meaning on name:
The name malloc means attributed to memory allocation.
The name calloc means contiguous allocation.

참고URL : https://stackoverflow.com/questions/1538420/difference-between-malloc-and-calloc

반응형