배열 유형과 malloc으로 할당 된 배열의 차이점
오늘 저는 C 코드로 제 친구를 돕고 있었는데 왜 그런 일이 발생했는지 설명 할 수없는 이상한 행동을 발견했습니다. 정수 목록이있는 TSV 파일이 있고 각 줄에 int가 있습니다. 첫 번째 줄은 목록에있는 줄 수입니다.
또한 매우 간단한 "readfile"이있는 ac 파일도 있습니다. 첫 번째 줄을 n, 즉 줄 수로 읽은 후 다음을 초기화했습니다.
int list[n]
마지막으로 fscanf가있는 n의 for 루프입니다.
작은 n (~ 100.000까지)의 경우 모든 것이 정상이었습니다. 그러나 n이 크면 (10 ^ 6) 세그 폴트가 발생한다는 것을 발견했습니다.
마지막으로 목록 초기화를 다음과 같이 변경했습니다.
int *list = malloc(n*sizeof(int))
그리고 아주 큰 n이 있어도 모든 것이 좋습니다.
누군가 이것이 왜 발생했는지 설명 할 수 있습니까? list = malloc (n * sizeof (int)) 사용을 시작할 때 중지 된 int list [n]으로 segfault의 원인은 무엇입니까?
여기에는 몇 가지 다른 조각이 있습니다.
첫 번째는 배열을 다음과 같이 선언하는 것의 차이점입니다.
int array[n];
과
int* array = malloc(n * sizeof(int));
첫 번째 버전에서는 자동 저장 기간이있는 개체를 선언합니다. 이것은 배열이 호출하는 함수가 존재하는 동안 만 존재 함을 의미합니다. 두 번째 버전에서는 동적 저장 기간이있는 메모리를 얻습니다. 즉, 명시 적으로 할당이 해제 될 때까지 존재합니다 free
.
두 번째 버전이 여기서 작동하는 이유는 C가 일반적으로 컴파일되는 방법에 대한 구현 세부 사항 때문입니다. 일반적으로 C 메모리는 스택 (함수 호출 및 로컬 변수 용) 및 힙 ( malloc
ed 객체 용)을 포함하여 여러 영역으로 분할됩니다 . 스택은 일반적으로 힙보다 크기가 훨씬 작습니다. 일반적으로 8MB 정도입니다. 결과적으로 거대한 배열을 다음과 같이 할당하려고하면
int array[n];
그러면 스택의 저장 공간을 초과하여 segfault가 발생할 수 있습니다. 반면에 힙은 일반적으로 큰 크기 (예 : 시스템에서 사용 가능한 공간만큼)를 가지므로 malloc
큰 개체를 사용 하더라도 메모리 부족 오류가 발생하지 않습니다.
일반적으로 C의 가변 길이 배열에주의하십시오. 스택 크기를 쉽게 초과 할 수 있습니다. malloc
크기가 작거나 실제로 짧은 시간 동안 만 어레이를 원하는 경우가 아니라면 선호하십시오 .
도움이 되었기를 바랍니다!
int list[n]
일반적으로 매우 작은 스택의n
정수 공간을 할당합니다 . 스택에서 메모리를 사용하는 것이 다른 방법보다 훨씬 빠르지 만, 크기가 매우 작고 거대한 배열을 할당하거나 너무 깊게 재귀를 수행하는 것과 같은 작업을 수행하면 스택을 오버플로 (즉, 너무 많은 메모리를 할당)하기 쉽습니다. 이러한 방식으로 할당 된 메모리를 수동으로 할당 해제 할 필요가 없습니다. 배열이 범위를 벗어날 때 컴파일러에서 수행합니다.
malloc
반면에 힙에 공간을 할당하며 일반적으로 스택에 비해 매우 큽니다 . 힙에 훨씬 많은 양의 메모리를 할당해야 소진되지만 스택보다 힙에 메모리를 할당하는 것이 훨씬 느리며 free
사용이 끝나면 수동으로 할당을 해제해야 합니다. .
int list [n]은 데이터를 스택에 저장하고 malloc은 데이터를 힙에 저장합니다.
스택이 제한되고 공간이 많지 않지만 힙은 훨씬 큽니다.
int list[n]
힙 대신 스택에 할당하는 VLA입니다. 해제 할 필요가 없으며 (함수 호출이 끝날 때 자동으로 해제 됨) 빠르게 할당되지만 저장소 공간은 매우 제한적입니다. 힙에 더 큰 값을 할당해야합니다.
이 선언은 스택에 메모리를 할당합니다.
int list[n]
malloc은 힙에 할당합니다.
스택 크기는 일반적으로 힙보다 작으므로 스택에 너무 많은 메모리를 할당하면 스택 오버플로가 발생합니다.
자세한 내용은 이 답변을 참조하십시오.
구현에 일반적인 구현이 있다고 가정하면 다음과 같습니다.
int list[n]
스택에 할당 된 목록입니다.
int *list = malloc(n*sizeof(int))
힙에 할당 된 메모리.
스택의 경우 일반적으로 확장 할 수있는 크기에 제한이 있습니다 (아예 확장 할 수있는 경우). 힙의 경우에도 여전히 제한이 있지만 RAM + 스왑 + 주소 공간에 의해 훨씬 더 크고 (광범위하게) 제한되는 경향이 있습니다. 이는 일반적으로 그 이상은 아니지만 일반적으로 10 배 이상 더 큰 크기입니다.
를 사용하여 할당하면 malloc
메모리가 스택이 아닌 힙에서 할당되므로 크기가 훨씬 더 제한됩니다.
Linux를 사용하는 경우 ulimit -s를 더 큰 값으로 설정할 수 있으며 스택 할당에도 작동 할 수 있습니다. 스택에 메모리를 할당하면 해당 메모리는 함수 실행이 끝날 때까지 유지됩니다. (malloc을 사용하여) 힙에 메모리를 할당하면 언제든지 (함수 실행이 끝나기 전이라도) 원하는 시간에 메모리를 해제 할 수 있습니다.
일반적으로 대용량 메모리 할당에는 힙을 사용해야합니다.
int array[n];
정적으로 할당 된 배열의 예이며 컴파일 시간에 배열의 크기를 알 수 있습니다. 그리고 어레이는 스택에 할당됩니다.
int *array(malloc(sizeof(int)*n);
동적으로 할당 된 배열의 예이며 배열의 크기는 런타임에 사용자에게 알려집니다. 그리고 배열은 힙에 할당됩니다.
'IT TIP' 카테고리의 다른 글
Java를 사용하여 프로세스 종료 (0) | 2020.11.29 |
---|---|
백 슬래시 인 경우 마지막 문자 제거 (0) | 2020.11.29 |
Java에서 임의의 부울 가져 오기 (0) | 2020.11.29 |
C #이 const 변수를 해당 값으로 바꾸는 것을 중지하는 방법은 무엇입니까? (0) | 2020.11.29 |
org.eclipse.jetty : jetty-maven-plugin으로 서버 포트를 설정하는 방법은 무엇입니까? (0) | 2020.11.29 |