malloc는 gcc에서 값을 0으로 초기화하는 이유는?
플랫폼마다 다르겠지만
gcc로 컴파일하고 아래 코드를 실행하면 ubuntu 11.10에서 매번 0을 받는다.
#include <stdio.h>
#include <stdlib.h>
int main()
{
double *a = malloc(sizeof(double)*100)
printf("%f", *a);
}
맬록은 왜 calloc가 있는데도 이렇게 행동할까?
때로는 원하지 않더라도 값을 0으로 초기화하기 위해 원하지 않는 성능 오버헤드가 있는 것은 아닐까?
편집: 아, 이전의 예시는 초기화가 아니라 우연히 "신선한" 블록을 사용했었습니다.
내가 정확히 찾고 있던 것은 왜 그것이 큰 블록을 할당할 때 그것을 초기화하느냐 하는 것이었다.
int main()
{
int *a = malloc(sizeof(int)*200000);
a[10] = 3;
printf("%d", *(a+10));
free(a);
a = malloc(sizeof(double)*200000);
printf("%d", *(a+10));
}
OUTPUT: 3
0 (initialized)
하지만 말로킹할 때 SECURITY 이유가 있다고 지적해줘서 고마워! (생각해 본 적 없어)새 블록 또는 큰 블록을 할당할 때 0으로 초기화해야 함을 확인하십시오.
짧은 답변:
그렇지 않아, 우연히 너의 경우 0이 되는 거야.
(또한 당신의 테스트 케이스는 데이터가 0이라는 것을 보여주지 않는다.원소 하나가 0인 경우에만 표시)
긴 답변:
전화할 때malloc()
다음 두 가지 중 하나가 발생할 것이다.
- 이전에 할당되어 같은 공정에서 해방되었던 기억을 재활용한다.
- 운영 체제에서 새 페이지를 요청한다.
첫 번째 경우, 메모리는 이전 할당에서 남은 데이터를 포함할 것이다.0이 되지 않도록.소규모 할당을 수행할 때 흔히 볼 수 있는 경우다.
두 번째 경우, 메모리는 OS에서 제공될 것이다.이는 프로그램의 메모리가 부족하거나 매우 많은 할당을 요청할 때 발생한다.(당신의 예에서와 같이)
여기서 주목해야 할 점은 OS에서 나오는 메모리는 보안상의 이유로 0이 된다는 것이다.*
OS가 메모리를 제공하면 다른 프로세스에서 해방될 수 있었다.그래서 메모리에 암호와 같은 중요한 정보가 포함될 수 있다.따라서 이러한 데이터를 읽지 못하도록 OS는 데이터를 제공하기 전에 데이터를 0으로 설정한다.
*C 표준에서는 이에 대해 아무 말도 하지 않는다는 점에 유의한다.이것은 엄밀히 말하면 OS 동작이다.따라서 이러한 영점 조정은 보안이 문제가 되지 않는 시스템에 존재할 수도 있고 없을 수도 있다.
여기에 더 많은 성능 배경을 제공하려면:
@R.에서 언급했듯이, 이 영점 조정은 당신이 항상 + 대신 사용해야 하는 이유 입니다.calloc()
이 사실을 이용하여 별개의 것을 피할 수 있다.memset()
.
반면에 이 영점 조정은 때때로 성능 병목현상이 된다.일부 숫자 애플리케이션(예: 외부 FFT)에서는 큰 스크래치 메모리 덩어리를 할당해야 한다.어떤 알고리즘을 사용하든, 그 후 자유로워질 수 있는 알고리즘을 사용하지 마십시오.
이 경우 영점화는 불필요하며 순수한 오버헤드에 해당한다.
내가 본 가장 극단적인 예는 48GB 스크래치 버퍼가 있는 70초 작업에 대한 오버헤드 20초 입니다. (오버헤드 30% 정도).(Granted: the machine did have a lack of memory bandwidth.)
분명한 해결책은 단순히 수동으로 메모리를 재사용하는 것이다.그러나 그것은 종종 확립된 인터페이스를 뚫어야 한다.(특히 라이브러리 루틴의 일부인 경우)
나는 너의 예시를 2개의 동일한 할당을 포함하도록 수정했다.이제 쉽게 볼 수 있게 되었다.malloc
초기화 메모리를 0으로 설정하지 않는다.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
{
double *a = malloc(sizeof(double)*100);
*a = 100;
printf("%f\n", *a);
free(a);
}
{
double *a = malloc(sizeof(double)*100);
printf("%f\n", *a);
free(a);
}
return 0;
}
gcc 4.3.4를 사용한 출력
100.000000
100.000000
왜 그렇게 생각하시죠?malloc()
으로 초기화으로 초기화하시겠습니까?도 古木(후루끼)도(후루끼)에게 첫 번째 가 걸려오는 이 바로 이다.malloc()
에게 전화를 걸게 되다.sbrk
또는mmap
로 제로 를 제공할 않으면OS는 보안상의 이유로 제로 초기화 메모리를 제공할 의무가 있다(그렇지 않으면 다른 프로세스의 데이터가 보인다!).그래서 여러분은 OS가 페이지를 0으로 만드는 데 시간을 낭비한다고 생각할지도 모른다.하지만!! 라고 특별한 시스템 , 그그리눅스에는 '제로 페이지'라고 불리는 특별한 시스템 차원의 싱글톤 페이지가 있으며, 그 페이지는 Copy-On-Write로 매핑될 것이며, 이는 당신이 그 페이지에 실제로 글을 쓸 때만 OS가 다른 페이지를 할당하고 초기화한다는 것을 의미한다.그래서 나는 이것이 성과에 관한 너의 질문에 대한 답이었으면 좋겠어.메모리 페이징 모델은 동일한 페이지의 다중 매핑 기능과 더불어 첫 번째 쓰기가 발생할 때 케이스를 처리할 수 있는 기능을 지원함으로써 메모리 사용이 일종의 게으름을 피울 수 있게 한다.
전화하면free()
그glibc
할당자는 해당 지역을 자유 목록으로 되돌리고, 언제malloc()
다시 부르면 같은 지역이 될 수도 있지만 이전 데이터로는 더러워질 수 있다. 국,free()
시스템 호출을 다시 호출하여 메모리를 OS로 되돌릴 수 있다.
다음 사항에 주목하십시오.glibc
맨 페이지malloc()
메모리가 지워지지 않는다고 엄격히 말하므로 API의 "계약"에 의해 지워진다고 가정할 수 없다.여기 원본 발췌본이 있다.
malloccript는 크기 바이트를 할당하고 할당된 메모리에 포인터를 반환한다.
기억이 지워지지 않는다.크기가 0이면 malloc()는 NULL 또는 나중에 free()로 성공적으로 전달할 수 있는 고유한 포인터 값을 반환한다.
성능이나 기타 부작용에 대해 염려하는 경우 해당 설명서에 대해 자세히 알아보십시오.
malloc
메모리를 0으로 초기화하지 않는다.그것은 기억을 건드리거나 그 가치를 바꾸지 않고 그대로 당신에게 돌려준다.
그렇다면, 우리는 왜 이 0들을 얻을까?
이 질문에 대답하기 전에 malloc가 어떻게 작동하는지 이해해야 한다.
때, 은 malloc를 호, 때,, thoughdenned 이이e malloce를 한다.glibc
할당자에 요청된 크기의 메모리가 있는지 여부.
만약 그렇게 된다면, 그것은 이 기억을 당신에게 되돌려 줄 것이다.이 기억은 보통 이전 기억 때문에 온다.free
대부분의 경우 가비지 값을 갖도록 작동한다.
반면 메모리를 찾을 수 없으면 OS에 전화를 걸어 메모리 할당을 요청한다.sbrk
또는mmap
의 이유로 하는데, 이 는 다른 수 있기 OS는 보안상의 이유로 초기화되지 않은 페이지를 반환하는데, 이 메모리는 다른 프로세스에서 사용되었을 수 있고 비밀번호나 개인 데이터 같은 귀중한 정보를 가지고 있을 수 있기 때문이다.
이 링크에서 직접 읽어보십시오.
이웃한 덩어리들은 크기가 어떻게 되든 무료로 합칠 수 있다.이는 단편화를 통해 일반적으로 높은 메모리 낭비를 초래하지 않고 모든 종류의 할당 패턴에 적합한 구현을 만든다.
이 구현에 의해 매우 큰 블록(페이지보다 훨씬 큰 블록)이 mmap(익명 또는 /dev/zero를 통해)로 할당된다.
에서는 다음과 같다.calloc
OS의 이 속성을 사용하고 OS에 페이지 할당을 요청하여 메모리 자체를 초기화하지 않고 항상 제로 초기화되도록 한다.
출처: gnu.org:
매우 큰 블록(페이지보다 훨씬 큰 블록)은 이 구현에 의해 mmap(익명 또는 /dev/zero를 통해)로 할당된다.
OS는 대개 이전 프로세스의 데이터를 볼 수 없도록 프로세스에 전송하는 새로운 메모리 페이지를 지운다.즉, 변수(또는 말로크)를 처음 초기화할 때는 0이 되는 경우가 많지만 그 메모리를 재사용할 경우(예를 들어, 자유화하여 다시 말로크잉) 모든 베팅이 해제된다.
이러한 불일치는 정확히 왜 초기화되지 않은 변수가 버그를 찾기가 어려운가 하는 것이다.
원치 않는 성능 오버헤드에 대해서는, 지정되지 않은 행동을 피하는 것이 아마도 더 중요할 것이다.이 경우 어떤 작은 성능 향상이라도 누군가가 코드를 약간 수정하거나(이전의 가정을 깨뜨리거나) 다른 시스템에 포팅(애초에 가정이 무효화되었을 수 있는 경우)해야 하는 버그를 찾기 어려운 문제를 보상하지 못할 것이다.
표준은 다음과 같은 것을 지시하지 않는다.malloc()
값을 0으로 초기화해야 한다.당신의 플랫폼에서 그것이 0으로 설정되었을 수도 있고, 당신이 그 값을 읽은 특정 순간에 0이 되었을 수도 있다.
네에 면에 면면 이라는 것을 .malloc
그 기억을 0으로 초기화한다.그것은 프로그램이 시작하기 전에 운영체제가 할 수 있다.shich가 그런 경우라면 메모리에 다른 값을 쓰고 자유롭게 한 다음 malloc를 다시 호출한다.아마 같은 주소를 받게 되겠지만, 이 주소를 확인해야 할 거야.만약 그렇다면, 여러분은 그것이 무엇을 포함하고 있는지 볼 수 있다.우리에게 알려줘!
당신은 그것이 확실히 초기화되고 있다는 것을 알고 있는가?malloc()으로 반환되는 지역이 단지 시작점에서 0을 가지는 경우가 빈번한 것이 가능한가?
어떤 컴파일러도 메모리를 어떤 것으로도 초기화할 코드를 생성하지 마십시오. malloc는 단순히 포인터를 n바이트의 메모리로 되돌릴 뿐이며, 심지어 스왑 상태일 수도 있다.
메모리 내용이 중요한 경우 직접 초기화하십시오.
참조URL: https://stackoverflow.com/questions/8029584/why-does-malloc-initialize-the-values-to-0-in-gcc
'Programing' 카테고리의 다른 글
META-INF의 목적은 무엇인가? (0) | 2022.05.02 |
---|---|
iOS는 기가바이트의 데이터를 저장할 때 진행형 웹 앱을 제한하는가? (0) | 2022.05.02 |
변환 장치의 일부에 대해서만 GCC 경고를 선택적으로 비활성화 (0) | 2022.05.02 |
Vuex 디스패치가 반환되지 않음 (0) | 2022.05.02 |
C에서 char 배열을 복사하는 방법? (0) | 2022.04.29 |