C에서 동적으로 할당 된 메모리의 크기 결정
C에서 동적으로 할당 된 메모리의 크기를 알아내는 방법이 있습니까?
예를 들어,
char* p = malloc (100);
관련된 메모리의 크기를 알아내는 방법이 p
있습니까?
때 때 comp.lang.c 자주하는 질문 목록 · 질문 7.27 -
Q. malloc
할당 된 블록의 크기를 확인하기 위해 패키지를 쿼리 할 수 있습니까?
A. 안타깝게도 표준 또는 추천 방법이 없습니다. (일부 컴파일러는 비표준 확장을 제공합니다.) 필요한 경우 직접 추적해야합니다. (질문 7.28 도 참조하십시오 .)
이 정보를 찾는 표준 방법은 없습니다. 그러나 일부 구현 msize
에서는 이와 같은 기능을 제공합니다 . 예를 들면 :
- Windows의 _msize
- MacOS의 malloc_size
- glibc가있는 시스템의 malloc_usable_size
하지만 malloc은 요청 된 최소 크기를 할당 할 구현 메모리에 대한 msize 변형이 생성 된 크기를 반환하거나 힙에 할당해야합니다.
C의 사고 방식은 프로그래머에게 작업의 본질을 바꾸는 추상화를 제공하는 것이 아니라 작업에 도움이되는 도구를 제공하는 것입니다. C는 또한 성능 제한을 강화하여 발생하는 경우를 더 안전하게 만드는 것을 방지합니다.
메모리 영역에서 수행 할 수있는 특정 작업에는 영역 시작 위치만이 필요합니다. 이러한 작업에는 널 (null)로 끝나는 문자열 작업 ,-domain 의보기 처음 N 바이트 조작 (영역이 적어도 이만큼 큰 것으로 알려진 경우) 등이 포함됩니다.
C가 자동으로 수행 할 작업을 수행 할 수 있습니다.
많은 라이브러리 함수 (예 fread()
:)는 영역의 시작에 대한 포인터 와이 영역의 크기가 필요합니다. 영역의 크기가 필요한 경우를 추적해야합니다.
예, malloc () 구현은 일반적으로 영역의 크기를 추적하지만 간접적으로 수행하거나 일부 값으로 반올림하거나 아예 유지하지 않을 수 있습니다. 이를 지원하지만,이 방법으로 크기를 찾는 것이 바로 추적하는 것에 느릴 수 있습니다.
각 지역의 크기를 아는 데이터 구조가 필요한 경우 C가 대신 할 수 있습니다. 영역의 크기와 영역에 대한 포인터를 추적하는 것을 사용하십시오.
아니요, C 런타임 라이브러리는 기능을 제공하지 않습니다.
일부 라이브러리는이 정보를 사용할 수있는 플랫폼 또는 특정 함수를 제공 할 수 있습니다. 일반적 으로이 정보를 추적하는 방법은 다른 정수 변수에 있습니다.
주소와 크기를 저장하기 위해 태그가 지정된 포인터를 만드는 가장 좋은 방법은 다음과 가변합니다. 모든 포인터는 여전히 예상대로 작동합니다.
도난 : https://stackoverflow.com/a/35326444/638848
또한 malloc에 대한 래퍼를 구현하고 malloc이 반환하는 포인터 태그 (할당 크기 및 기타 메타 정보 등)를 자유롭게 사용할 수 있습니다. 이것은 실제로 C ++ 컴파일러가 가상 클래스에 대한 참조로 객체에 태그를 지정하는 방법입니다. 다음은 작동하는 한 가지 예입니다.
#include <stdlib.h> #include <stdio.h> void * my_malloc(size_t s) { size_t * ret = malloc(sizeof(size_t) + s); *ret = s; return &ret[1]; } void my_free(void * ptr) { free( (size_t*)ptr - 1); } size_t allocated_size(void * ptr) { return ((size_t*)ptr)[-1]; } int main(int argc, const char ** argv) { int * array = my_malloc(sizeof(int) * 3); printf("%u\n", allocated_size(array)); my_free(array); return 0; }
크기와 포인터가있는 구조에 비해이 방법의 장점
struct pointer { size_t size; void *p; };
malloc과 무료 통화 만 교체하면됩니다. 다른 모든 포인터 작업에는 리팩토링이 필요하지 않습니다.
다른 모든 사람들이 이미 말했듯이 : 없습니다.
또한 여기에서는 모든 공급 업체별 기능을 항상 피할 것입니다. 왜냐하면 일반적으로 잘못하고 있다는 것을 알게됩니다. 크기를 저장하거나 전혀 알 필요가 없습니다. 벤더 함수를 사용하는 것은 가장 빠른 방법입니다.
나는 이것이 구현에 따라 기대합니다.
헤더 데이터 구조를 얻은 경우 포인터에서 다시 캐스팅하여 크기를 얻을 수 있습니다.
그것은 불가능한 말하는 모든 사람은 기술적으로 말하는 것입니다.
엔지니어링상의 재구성 malloc 서브 시스템에 의존하여 할당 된 블록의 크기를 정확하게 알려주는 좋지 않습니다. 이를 확신하기 위해 여러 메모리 할당을 사용 하여하여 다수의 응용 프로그램 을 구축하고 상상해 malloc
. 한 부분에서는 원시 libc를 사용 operator new
하고 다른 부분에서는 C ++를 사용 하고 있으며 특정 Windows API를 사용할 수 있습니다. 그래서 당신은 온갖 종류의 void*
비행을하고 있습니다. 포인터의 값에서 어떤 힙에서 왔는지 알 수없는 기능 들 중 하나에서 작동하는 함수를 작성하는 void*
것은 불가능합니다.
따라서 프로그램의 각 포인터를 포인터의 출처 (및 포인터를 반환하는 위치)를 사용하여 래핑 할 수 있습니다. 예를 들어, C ++에서 우리는 std::unique_ptr<void>
( operator delete
'd std::unique_ptr<void, D>
가 필요한 포인터의 경우 ) 또는 (다른 똑같이 통해 반환되어야하는 포인터의 경우 ) 이를 호출합니다 D
. 같은 C 같은 일을 할 수 있습니다. 어쨌든 더 큰 걱정할로 포인터를 래핑 하면 작은 단계에 struct SizedPtr { void *ptr; size_t size; }
불고기 할당 크기에 대해 다시는 필요가 없습니다.
하나.
있습니다 또한 당신이 합법적으로 할당의 실제 기본 크기를 알아야 할 수 있습니다 좋은 이유는. 예를 들어, 프로그래머 가 사용하고 있다고 생각한 메모리 양뿐만 아니라 각 하위 시스템에서 사용 하는 실제 메모리 양을보고하는 앱용 프로파일 링 도구를 작성하고있을 수 있습니다 . 각 10 바이트 할당이 비밀리에 16 바이트를 사용하고 권한 알아두면 좋습니다! (물론이 방식으로 측정하지 않는 다른 오버 헤드도있을 것입니다.하지만 해당 작업을 위한 다른 도구가 아직 있습니다 .) 아니면 플랫폼에서 의 동작을 조사하고 가능성이 있습니다 . 또는 조기 할당을 방지하기 위해 증가하는 할당의 용량을 "반올림"하고 싶을 수도 있습니다.realloc
재 할당. 예 :
SizedPtr round_up(void *p) {
size_t sz = portable_ish_malloced_size(p);
void *q = realloc(p, sz); // for sanitizer-cleanliness
assert(q != NULL && portable_ish_malloced_size(q) == sz);
return (SizedPtr){q, sz};
}
bool reserve(VectorOfChar *v, size_t newcap) {
if (v->sizedptr.size >= newcap) return true;
char *newdata = realloc(v->sizedptr.ptr, newcap);
if (newdata == NULL) return false;
v->sizedptr = round_up(newdata);
return true;
}
사용자 정의 힙이 아니라 객체 중간을 가리 키지 않는 libc malloc에서 직접 반환 된 null이 아닌 포인터 뒤의 할당 크기를 얻을 수있는 다음과 같은 OS 별 API를 사용할 수 있습니다. 편의를 위해 "휴대용"래퍼 기능으로 묶었습니다. 이 코드가 작동하지 않는 일반적인 시스템을 찾으면 댓글을 애무 주시면 수정하겠습니다!
#if defined(__linux__)
// https://linux.die.net/man/3/malloc_usable_size
#include <malloc.h>
size_t portable_ish_malloced_size(const void *p) {
return malloc_usable_size((void*)p);
}
#elif defined(__APPLE__)
// https://www.unix.com/man-page/osx/3/malloc_size/
#include <malloc/malloc.h>
size_t portable_ish_malloced_size(const void *p) {
return malloc_size(p);
}
#elif defined(_WIN32)
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/msize
#include <malloc.h>
size_t portable_ish_malloced_size(const void *p) {
return _msize((void *)p);
}
#else
#error "oops, I don't know this system"
#endif
#include <stdio.h>
#include <stdlib.h> // for malloc itself
int main() {
void *p = malloc(42);
size_t true_length = portable_ish_malloced_size(p);
printf("%zu\n", true_length);
}
테스트 대상 :
- Visual Studio, Win64 —
_msize
- GCC / Clang, glibc, Linux —
malloc_usable_size
- Clang, libc, Mac OS X —
malloc_size
- Clang, jemalloc, Mac OS X — 실제로 작동하지만 믿을 수 없습니다 (제말 록
malloc
과 내장 libc를 자동으로 혼합malloc_size
) - Linux 에서 jemalloc 과 잘 작동해야합니다.
- 없이 컴파일하면 Linux 에서 dlmalloc 과 잘 작동합니다.
USE_DL_PREFIX
- 모든 곳 에서 tcmalloc 과 잘 작동해야합니다.
malloc을 사용하면 크기를 얻을 수 없습니다.
반면에 Windows 힙 함수 와 같이 OS API를 사용하여 동적으로 메모리를 할당 하면 그렇게 할 수 있습니다.
이제 나는 이것이 당신의 특정 질문에 대한 답이 아니라는 것을 알고 있지만, 상자 밖에서 생각하면 ... 아마 당신이 알 필요가 없을 것입니다. Ok, ok, no 나는 당신이 나쁘거나 비 정통적인 구현을 가지고 있다는 것을 의미하지는 않습니다. 할당 된 메모리에서이 경우이 솔루션이 더 좋을 수 있습니다. 너무 많은 오버 헤드를 제공해서는 안되며 실제로 처리중인 경우 "적합"문제를 해결할 것입니다.
if ( p != (tmp = realloc(p, required_size)) ) p = tmp;
또는 이전 내용을 유지해야하는 경우 :
if ( p != (tmp = realloc(p, required_size)) ) memcpy(tmp, p = tmp, required_size);
물론 다음을 사용할 수 있습니다.
p = realloc(p, required_size);
그리고 그것으로 끝납니다.
이 코드는 대부분의 Windows 설치에서 작동합니다.
template <class T>
int get_allocated_bytes(T* ptr)
{
return *((int*)ptr-4);
}
template <class T>
int get_allocated_elements(T* ptr)
{
return get_allocated_bytes(ptr)/sizeof(T);
}
코드의 작은 업데이트가 작동 할 수 있습니다.
void* inc = (void*) (++p)
size=p-inc;
그러나 이것은와 관련, 메모리 즉, 1을 발생합니다 p
이 경우는 char*
. 그렇다면 int*
결과는 4가됩니다.
총 할당량을 알 수있는 방법은 없습니다.
Quuxplusone은 다음과 같이 썼습니다. "포인터의 값에서 어떤 힙에서 왔는지 알 수 없다면 이러한 void *에 대해 작동 할 수있는 함수를 작성하는 것은 불가능합니다." C " 에서 동적으로 할당 된 메모리 크기 결정
실제로 Windows에서 _msize는 포인터 값에서 할당 된 메모리 크기를 제공합니다. 주소에 할당 된 메모리가 없으면 오류가 발생합니다.
int main()
{
char* ptr1 = NULL, * ptr2 = NULL;
size_t bsz;
ptr1 = (char*)malloc(10);
ptr2 = ptr1;
bsz = _msize(ptr2);
ptr1++;
//bsz = _msize(ptr1); /* error */
free(ptr2);
return 0;
}
#define 컬렉션에 감사드립니다. 다음은 매크로 버전입니다.
#define MALLOC(bsz) malloc(bsz)
#define FREE(ptr) do { free(ptr); ptr = NULL; } while(0)
#ifdef __linux__
#include <malloc.h>
#define MSIZE(ptr) malloc_usable_size((void*)ptr)
#elif defined __APPLE__
#include <malloc/malloc.h>
#define MSIZE(ptr) malloc_size(const void *ptr)
#elif defined _WIN32
#include <malloc.h>
#define MSIZE(ptr) _msize(ptr)
#else
#error "unknown system"
#endif
참조 URL : https://stackoverflow.com/questions/1281686/determine-size-of-dynamically-allocated-memory-in-c
'ProgramingTip' 카테고리의 다른 글
C ++로 통화 값을 저장하는 가장 좋은 방법 (0) | 2021.01.10 |
---|---|
Mercurial 작업 트리에서 모든 .orig 파일을 자동으로 제거하는 방법은 무엇입니까? (0) | 2021.01.10 |
Lua- 테이블 병합? (0) | 2021.01.10 |
JPA, Mysql Blob이 너무 긴 데이터를 반환 함 (0) | 2021.01.10 |
데이터베이스 연결을 닫는 가장 좋은 장소 (0) | 2021.01.10 |