수행의 차이점은 무엇입니까?
ptr = (char **) malloc (MAXELEMS * sizeof(char *));
또는:
ptr = (char **) calloc (MAXELEMS, sizeof(char*));
malloc 대신 calloc을 사용하거나 그 반대로 사용하는 것이 좋은 생각은 언제입니까?
ptr = calloc(MAXELEMS, sizeof(*ptr));
수행의 차이점은 무엇입니까?
ptr = (char **) malloc (MAXELEMS * sizeof(char *));
또는:
ptr = (char **) calloc (MAXELEMS, sizeof(char*));
malloc 대신 calloc을 사용하거나 그 반대로 사용하는 것이 좋은 생각은 언제입니까?
ptr = calloc(MAXELEMS, sizeof(*ptr));
답변:
calloc()초기화 malloc()되지 않은 버퍼를 제공하는 동시에 메모리는 초기화되지 않습니다.
대규모 할당의 경우 calloc주류 OS에서 구현되는 대부분의 구현은 OS에서 0으로 알려진 페이지 (예 : POSIX mmap(MAP_ANONYMOUS)또는 Windows 를 통해)를 가져 오므 VirtualAlloc로 사용자 공간에이를 작성할 필요가 없습니다. 이것은 정상적인 방법으로 mallocOS에서 더 많은 페이지를 얻는 방법입니다 . callocOS 보증을 활용합니다.
이것은 calloc메모리가 여전히 "깨끗하고"느리게 할당 될 수 있으며, 기록 중 복사가 시스템 전체의 공유 물리적 페이지 0에 매핑 될 수 있음을 의미 합니다. (가상 메모리가있는 시스템을 가정합니다.)
일부 컴파일러는 malloc + memset (0)을 calloc으로 최적화 할 수도 있지만 메모리를로 읽으려면 calloc을 명시 적으로 사용해야합니다 0.
쓰기 전에 메모리를 읽지 않으 malloc려면 OS에서 새 페이지를 가져 오는 대신 내부 여유 목록에서 더티 메모리를 제공 할 수 있습니다. (또는 작은 할당을 위해 사용 가능한 목록에서 메모리 블록을 0으로 만드는 대신).
OS가없는 경우 임베디드 구현은 메모리를 제로 메모리 calloc로 남겨 두거나 calloc프로세스 간 정보 유출을 막기 위해 페이지를 0으로 만드는 멋진 다중 사용자 OS가 아닙니다.
임베디드 Linux에서 malloc은 mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS)다중 사용자 시스템에서 안전하지 않기 때문에 일부 임베디드 커널에서만 사용할 수 있습니다.
callocOS가 속도를 높이기 위해 몇 가지 트릭을 수행 할 수 있기 때문에 반드시 더 비싸지는 않습니다. FreeBSD는 유휴 CPU 시간이되면 그것을 사용하여 할당 취소 된 메모리 블록을 없애고 블록으로 플래그를 표시하는 간단한 프로세스를 실행하는 데 사용합니다. 그래서 당신이 할 때 calloc, 그것은 먼저 사전에 0으로 된 블록 중 하나를 찾아서 당신에게 줄 것입니다-대부분 그것을 찾을 것입니다.
덜 알려진 차이점은 Linux와 같이 낙관적 메모리 할당을 사용하는 운영 체제 malloc에서 프로그램이 실제로 해당 메모리에 닿을 때까지 반환되는 포인터 가 실제 메모리에 의해 지원되지 않는다는 것입니다.
calloc실제로 메모리를 만지므로 (0을 씁니다) 따라서 OS가 실제 RAM (또는 스왑)으로 할당을 백업하고 있는지 확인할 수 있습니다. 이것이 malloc보다 속도가 느린 이유이기도합니다 (0으로 설정해야 할뿐만 아니라 OS는 다른 프로세스를 교체하여 적절한 메모리 영역을 찾아야합니다).
malloc의 동작에 대한 추가 논의는 예를 들어이 SO 질문 을 참조하십시오
calloc0을 쓸 필요가 없습니다. 할당 된 블록이 운영 체제에서 제공하는 대부분의 새 0 페이지로 구성되어 있으면 해당 블록은 그대로 유지됩니다. 물론 이것은 calloc일반 라이브러리 함수 대신 운영 체제에 맞게 조정해야합니다 malloc. 또는 구현 calloc자는 각 단어를 0 화하기 전에 0과 비교할 수 있습니다. 시간이 절약되지는 않지만 새 페이지가 더러워지지는 않습니다.
dlmalloc유사 구현 memset은 mmap새 익명 페이지 (또는 이와 동등한) 를 통해 청크를 얻은 경우 생략합니다 . 일반적으로 이러한 종류의 할당은 256k 정도에서 시작하여 더 큰 청크에 사용됩니다. 나는 제 자신을 제외하고 0을 쓰기 전에 0과 비교하는 구현을 모른다.
omalloc또한 memset; calloc응용 프로그램에서 아직 사용하지 않은 페이지 (페이지 캐시)를 건드리지 않아도됩니다. 그러나 매우 원시적 인 calloc구현 은 다릅니다.
종종 간과되는 장점 중 하나 calloc는 (적합한 구현) 정수 오버플로 취약점으로부터 사용자를 보호하는 데 도움이된다는 것입니다. 비교:
size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);
vs.
size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);
전자 count가보다 크면 작은 할당 및 후속 버퍼 오버플로가 발생할 수 있습니다 SIZE_MAX/sizeof *bar. 이 경우 후자는 큰 개체를 만들 수 없으므로 자동으로 실패합니다.
물론 오버플로 가능성을 무시하는 부적합한 구현에주의를 기울여야 할 수도 있습니다. 이것이 목표로하는 플랫폼에서 문제가된다면 어쨌든 오버플로에 대한 수동 테스트를 수행해야합니다.
char이다 하지 (A) 내로 결과 다시 할당하는 경우에 오버 플로우가 아니라 구현 정의 변환 char개체.
size_t64 비트이므로 문제 없습니다"인 경우 보안 버그로 이어질 잘못된 사고 방식입니다. size_t는 크기를 나타내는 추상 유형이며 32 비트 숫자의 임의의 곱을 생각할 이유가 없으며 size_t(참고 : sizeof *bar64 비트 C 구현에서는 원칙적으로 2 ^ 32보다 클 수 있습니다!)에 적합 size_t합니다.
이 문서는 calloc을 malloc처럼 보이게 만듭니다. 메모리는 0으로 초기화됩니다. 이것은 주요 차이점이 아닙니다! calloc의 아이디어는 메모리 할당을위한 copy-on-write 의미를 생략하는 것입니다. calloc을 사용하여 메모리를 할당하면 모든 물리적 페이지가 0으로 초기화되는 동일한 물리적 페이지에 매핑됩니다. 할당 된 메모리의 임의의 페이지가 물리적 페이지에 기록 될 때 할당됩니다. 예를 들어 비어있는 해시 부분이 추가 메모리 (페이지)에 의해 백업되지 않기 때문에 HUGE 해시 테이블을 만드는 데 종종 사용됩니다. 그것들은 행복하게 초기화 된 단일 페이지를 가리키며 프로세스 간에도 공유 할 수 있습니다.
모든 가상 주소에 쓰기는 페이지에 맵핑되며, 해당 페이지가 0 페이지 인 경우 다른 물리적 페이지가 할당되고 0 페이지가 복사되고 제어 플로우가 클라이언트 프로세스로 리턴됩니다. 메모리 매핑 파일, 가상 메모리 등이 작동하는 방식과 동일하게 작동합니다. 페이징을 사용합니다.
여기 주제에 대한 최적화 이야기가 있습니다 : http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/
할당 된 메모리 블록의 크기에는 차이가 없습니다. calloc메모리 블록을 물리적 인 0 비트 패턴으로 채 웁니다. 실제로 할당 된 메모리 블록에있는 객체 calloc는 마치 리터럴로 초기화 된 것처럼 초기 값 을 갖는다 고 가정합니다 0. 즉, 정수는 0부동 소수점 변수 -value- 0.0포인터-적절한 null 포인터 값 , 등등.
그러나 pedantic 관점에서 calloc(뿐만 아니라 memset(..., 0, ...)) 유형의 객체를 (0으로) 올바르게 초기화하는 것만 보장됩니다 unsigned char. 다른 모든 것은 제대로 초기화되지 않으며 , 소위 트랩 표현을 포함하여 정의되지 않은 동작을 유발할 수 있습니다. 다시 말해서, unsigned char상기 언급 된 모든 0 비트 이외 의 유형에 대해 patterm은 잘못된 값, 트랩 표현을 나타낼 수 있습니다.
나중에 Technical Corrigenda to C99 표준 중 하나에서 동작은 모든 정수 유형에 대해 정의되었습니다. 즉, 공식적으로 현재 C 언어에서는 calloc(및 memset(..., 0, ...))로 정수 유형 만 초기화 할 수 있습니다 . 일반적인 경우에이를 사용하여 C 언어의 관점에서 정의되지 않은 동작이 발생합니다.
실제로, calloc우리 모두가 알고 있듯이 작동하지만, 위의 사항을 고려할 것인지의 여부는 귀하에게 달려 있습니다. 나는 개인적으로 그것을 완전히 피하고 malloc대신 사용하고 내 자신의 초기화를 수행 하는 것을 선호합니다 .
마지막으로, 또 다른 중요한 세부 사항은 요소 크기에 요소 수를 곱하여 calloc최종 블록 크기를 내부적 으로 계산하는 데 필요 하다는 것 입니다 . 그렇게하는 동안 calloc산술 오버플로가 발생할 수 있는지 확인 해야합니다. 요청 된 블록 크기를 올바르게 계산할 수 없으면 할당 실패 (널 포인터)가 발생합니다. 한편,malloc 버전은 오버플로를 감시하지 않습니다. 오버플로가 발생하는 경우 "예측할 수없는"메모리 양을 할당합니다.
memset(p, v, n * sizeof type);가 발생할 수 있기 때문에 문제가 되는 것 같습니다 n * sizeof type. for(i=0;i<n;i++) p[i]=v;강력한 코드를 위해 루프 를 사용해야 할 것 같아요 .
n요소의 크기가있는 요소가 있는 배열 이 있으면 객체의 최대 크기가보다 작아야하므로 오버플 sizeof type로 n*sizeof type할 수 없습니다 SIZE_MAX.
SIZE_MAX이지만 여기 에는 배열 이 없습니다 . 에서 반환 된 포인터 calloc()가 초과 한 것보다 할당 된 메모리를 가리킬 수 있습니다 SIZE_MAX. 대부분의 구현에 2 개 인수의 제품을 제한 할 calloc()에 SIZE_MAX, 아직 C 사양은 제한을 부과하지 않습니다.
기사의 은 calloc 재미를 벤치마킹 () 및 제로 페이지 에 게오르그 헤거의 블로그
calloc ()을 사용하여 메모리를 할당 할 때 요청 된 메모리 양이 즉시 할당되지 않습니다. 대신, 메모리 블록에 속하는 모든 페이지는 일부 MMU 매직 (아래 링크)에 의해 모든 0을 포함하는 단일 페이지에 연결됩니다. 이러한 페이지가 읽기 전용 인 경우 (원래 벤치 마크 버전의 배열 b, c 및 d에 해당) 데이터는 단일 제로 페이지에서 제공되며 물론 캐시에 적합합니다. 메모리 바운드 루프 커널의 경우 너무 많습니다. 어떤 방법 으로든 페이지에 쓰면 오류가 발생하고 "실제"페이지가 매핑되고 0 페이지가 메모리에 복사됩니다. 이것을 잘 알려진 최적화 접근 방식 (copy-on-write)이라고합니다 (C ++ 강의에서 여러 번 가르쳤습니다). 그 후
calloc일반적 malloc+memset으로 0입니다
일반적으로 malloc+memset다음과 같은 작업을 수행 할 때 명시 적 으로 사용하는 것이 약간 좋습니다 .
ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));
sizeof(Item)컴파일 타임에 컴파일러에 대해 알고 있기 때문에 컴파일러 가 더 좋으며 대부분의 경우 컴파일러는 메모리를 제로화하는 가장 좋은 명령으로 대체합니다. 반면에에서 memset발생 calloc하는 경우 할당의 매개 변수 크기가 calloc코드 에서 컴파일되지 않고 실제 memset호출되는 경우가 많습니다. 여기에는 일반적으로 채우기주기보다 긴 경계까지 바이트 단위 채우기를 수행하는 코드가 포함됩니다. sizeof(long)청크 단위로 메모리를 채우고 마지막으로 남은 공간을 바이트 단위로 채 웁니다. 할당자가 일부를 호출하기에 충분히 똑똑하더라도aligned_memset 여전히 일반 루프입니다.
주목할만한 예외는 매우 큰 메모리 청크 (일부 power_of_two 킬로바이트)의 malloc / calloc을 수행하는 경우 커널에서 직접 할당을 수행 할 수 있습니다. OS 커널은 일반적으로 보안상의 이유로 모든 메모리를 제로화하므로, 충분한 calloc은 추가 제로화로이를 반환 할 수 있습니다. 다시 말하지만, 당신이 아는 것을 할당하는 것이 작 으면 malloc + memset 성능 측면에서 더 나을 수 있습니다.
calloc()느립니다 malloc(): 크기의 곱셈. malloc ()은 종종 컴파일 시간 상수를 갖는 반면 calloc()일반 곱셈 ( size_t64 비트 인 경우에도 매우 비싼 64 비트 * 64 비트 = 64 비트 연산) 을 사용해야합니다 .
struct foo { char a,b,c; };. calloc항상 전체 에드 영역 을 지우려면 항상 malloc+ 보다 낫습니다 . 크기 요소의 int overflow에 대해서도 신중하지만 효율적으로 검사합니다. memsetmalloccalloc
차이 1 :
malloc() 일반적으로 메모리 블록을 할당하고 초기화 된 메모리 세그먼트입니다.
calloc() 메모리 블록을 할당하고 모든 메모리 블록을 0으로 초기화합니다.
차이 2 :
malloc()구문 을 고려하면 하나의 인수 만 사용합니다. 아래의 다음 예를 고려하십시오.
data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );
예 : int 유형에 10 개의 메모리 블록을 할당하려면
int *ptr = (int *) malloc(sizeof(int) * 10 );
calloc()구문 을 고려하면 2 개의 인수가 필요합니다. 아래의 다음 예를 고려하십시오.
data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));
예 : int 유형에 10 블록의 메모리를 할당하고 모든 것을 ZERO에 초기화하려면
int *ptr = (int *) calloc(10, (sizeof(int)));
유사성:
모두 malloc()와 calloc()그들이 주조 입력하지 않으면 기본적으로 무효 *를 반환합니다.!
두 가지 차이점이 있습니다.
첫째, 논쟁의 수입니다. malloc()단일 인수 (바이트 단위의 메모리 필요)를 사용하지만 calloc()두 개의 인수가 필요합니다.
둘째, 할당 된 메모리를 초기화 malloc()하지 않고 calloc()할당 된 메모리를 ZERO로 초기화합니다.
calloc()메모리 영역을 할당하면 길이는 매개 변수의 곱이됩니다. calloc메모리를 ZERO로 채우고 첫 번째 바이트에 대한 포인터를 반환합니다. 충분한 공간을 찾지 못하면 NULL포인터를 반환합니다 .구문 : ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block);
즉ptr_var=(type *)calloc(n,s);
malloc()REQUSTED SIZE의 단일 메모리 블록을 할당하고 첫 번째 바이트에 대한 포인터를 반환합니다. 요청 된 메모리 양을 찾지 못하면 널 포인터를 리턴합니다.구문 : 그동안 함수는, 바이트 수를 할당하는 하나 개의 인자를 취할 기능 소자의 개수 인, 한 개의 인수를, 다른 바이트의 수는 이러한 요소들의 각각에 할당하도록되어있는 것을 특징으로한다. 또한 할당 된 공간을 0으로 초기화하지만 그렇지는 않습니다.ptr_var=(cast_type *)malloc(Size_in_bytes);malloc()calloc()calloc()malloc()
malloc() 과 calloc() 둘 다 런타임 메모리 할당을 허용 즉, 동적 메모리 할당을 허용 C 표준 라이브러리 함수이다.
프로토 타입은 다음과 같습니다.
void *malloc( size_t n);
void *calloc( size_t n, size_t t)
이 둘 사이에는 주로 두 가지 차이점이 있습니다.
동작 : malloc()메모리 블록을 초기화하지 않고 할당하고이 블록에서 내용을 읽으면 가비지 값이 발생합니다. calloc()반면에, 메모리 블록을 할당하고이를 0으로 초기화하며,이 블록의 내용을 읽으면 분명히 0이됩니다.
구문 : malloc()1 calloc()개의 인수 ( 할당 된 크기)를 취하고 두 개의 인수 (할당 된 블록 수와 각 블록의 크기)를 사용합니다.
성공했을 경우, 양쪽으로부터의 반환 값은 할당 된 메모리 블록에 대한 포인터입니다. 그렇지 않으면 메모리 할당 실패를 나타내는 NULL 이 반환됩니다.
예:
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));
동일한 기능은 다음과 같이 calloc()하여 얻을 수 malloc()와 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));
더 빠르기 때문에 malloc()사용 하는 것이 바람직 calloc()합니다. 값을 0으로 초기화하려는 경우 calloc()대신 사용하십시오.
아직 언급되지 않은 차이점 : 크기 제한
void *malloc(size_t size)까지만 할당 할 수 SIZE_MAX있습니다.
void *calloc(size_t nmemb, size_t size); 에 대해 할당 할 수 있습니다 SIZE_MAX*SIZE_MAX .
이 기능은 선형 주소 지정 기능이있는 많은 플랫폼에서 자주 사용되지 않습니다. 이러한 시스템 calloc()은nmemb * size <= SIZE_MAX .
512 바이트 유형을 호출 disk_sector하고 코드에서 많은 섹터 를 사용하려고합니다 . 여기서 코드는 SIZE_MAX/sizeof disk_sector섹터 까지만 사용할 수 있습니다 .
size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);
더 큰 할당을 허용하는 다음을 고려하십시오.
size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);
이제 그러한 시스템이 그러한 큰 할당을 제공 할 수 있다면 또 다른 문제입니다. 오늘날 대부분은 그렇지 않습니다. 때 그러나 그것은 몇 년 동안 발생한 SIZE_MAX감안할 때 65535이었다 무어의 법칙을 이 특정와 메모리 모델 2030에 대해 발생 될 것입니다 의심 SIZE_MAX == 4294967295기가 바이트의 100와 메모리 풀.
size_t32 비트보다 크게 만듭니다 . 유일한 질문은 더 작은 할당에 대한 포인터를 반환하지 않고 calloc제품이 초과하는 값을 사용하여 SIZE_MAX0을 산출 할 수 있는지 여부 입니다.
calloc()할당량을 초과 할 수 있습니다 SIZE_MAX. 16 비트로 과거에 발생했으며 size_t메모리가 계속 저렴 해짐에 따라 일반적 이지 않더라도 앞으로 나아갈 수는 없습니다 .
SIZE_MAX. 그러한 할당이 성공할 수있는 상황이 반드시 필요한 것은 아니다. 그러한 할당을 처리 할 수없는 구현이 반환해야한다는 위임이 특별한 이점이 있는지 확실하지 않습니다 NULL(특히 일부 구현에서 malloc아직 커밋되지 않았고 코드가 실제로 사용하려고 할 때 사용할 수없는 공간에 대한 포인터를 반환 하는 것이 일반적 임) 그것).
size_t에 uint64_t?
블록 수 :
malloc ()은 요청 된 메모리의 단일 블록을 할당하고
calloc ()은 요청 된 메모리의 여러 블록을 할당합니다
초기화 :
malloc ()-할당 된 메모리를 지우고 초기화하지 않습니다.
calloc ()-할당 된 메모리를 0으로 초기화합니다.
속도 :
malloc ()이 빠릅니다.
calloc ()이 malloc ()보다 느립니다.
인수 및 구문 :
malloc ()은 1 개의 인수를 사용합니다.
바이트
calloc ()은 2 개의 인수를받습니다 :
길이
void *malloc(size_t bytes);
void *calloc(size_t length, size_t bytes);
메모리 할당 방식 :
malloc 함수는 사용 가능한 힙에서 원하는 '크기'의 메모리를 할당합니다.
calloc 함수는 'num * size'와 같은 크기의 메모리를 할당합니다.
이름에 대한 의미 :
malloc이라는 이름은 "메모리 할당"을 의미합니다.
calloc이라는 이름은 "연속 할당"을 의미합니다.
malloc가족 의 결과를 캐스트하지 않습니다