C에서 동적으로 할당된 메모리의 크기를 확인합니다.
C에서 동적으로 할당된 메모리의 크기를 알 수 있는 방법이 있습니까?
예를 들어, 다음에
char* p = malloc (100);
'메모리 사이즈'에 관련된 알 수 있는 요?p
이 정보를 찾는 표준 방법은 없습니다.일부 기능을 합니다.msize
이 일을 하기 위해서.예를 들어 다음과 같습니다.
- Windows 에서는 _msize
- MacOS에서의 malloc_size
- glibc가 있는 시스템의 malloc_usable_size
단, malloc은 요청된 최소 크기를 할당하므로 구현용 msize variant가 실제로 개체 또는 힙에 할당된 메모리의 크기를 반환하는지 확인해야 합니다.
comp.lang.c FAQ 목록 · 질문 7.27 -
해도 될까요?
malloc
할당된 블록의 크기를 확인하기 위한 패키지입니다.A. 안타깝게도 표준 또는 휴대용 방법은 없습니다. (컴파일러에 따라서는 비표준 확장자가 제공됩니다.)알고 싶으면 직접 추적해야 해(질문 7.28도 참조).
불가능하다고 말하는 모든 사람이 기술적으로 옳다.
공학적 이유로 malloc 서브시스템에 의존하여 할당된 블록의 크기를 정확하게 파악하는 것은 좋지 않습니다.이를 확신하기 위해 여러 개의 서로 다른 메모리 할당기를 사용하여 대규모 애플리케이션을 작성하고 있다고 가정합니다.아마 raw libc를 사용하고 있을 것입니다.malloc
는 C++는 C++는 C++는 C++는 C++는 C로 있다.operator new
다른 부분에서 특정 Windows API를 사용하고, 또 다른 부분에서 특정 Windows API를 사용하고 있습니다.은 온갖 의 것을 있군요.void*
날아다닌다.다음 중 하나에서 사용할 수 있는 기능 쓰기void*
포인터의 값에서 어떤 더미의 출처를 알 수 없는 한 불가능합니다.
따라서 프로그램의 각 포인터를 포인터의 출처와 반환처를 나타내는 규칙과 함께 정리할 수 있습니다.를 들어C++에서는 그것을 C++, 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에서 직접 반환된 늘 이외의 포인터의 할당 크기를 얻으려면 다음 OS 고유의 API를 사용할 수 있습니다.이 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 -
- GCC/Clang, glibc, Linux -
- Clang, libc, Mac OS X -
- X:하지 않습니다, jemalloc, Mac OS X를 혼재시킵니다).
malloc
libc의 'Libcmalloc_size
) - Linux의 jemalloc에서는 정상적으로 동작합니다.
- Linux에서 dlmalloc을 컴파일하지 않으면 정상적으로 동작합니다.
USE_DL_PREFIX
- 모든 곳에 TCMalloc이 있으면 정상 작동해야 합니다.
C의 사고방식은 프로그래머에게 자신의 일을 도와주는 도구를 제공하는 것이지, 그의 직업의 성격을 바꾸는 추상적인 개념을 제공하는 것은 아니다.또, C는, 퍼포먼스 제한을 희생하고, 이러한 상황이 발생했을 경우, 상황을 보다 용이하게/안전하게 하는 것을 회피하려고 합니다.
메모리 영역에 대해 수행할 수 있는 특정 작업은 영역의 시작 위치만 필요합니다.이러한 작업에는 늘 종단 문자열 사용, 영역의 첫 번째 n바이트 조작(영역이 적어도 이 정도로 큰 것으로 알려진 경우) 등이 포함됩니다.
기본적으로 지역 길이를 추적하는 것은 추가 작업이며, C가 자동으로 추적하면 불필요할 수 있습니다.
기능: " " " " 등)fread()
부분에 포인터가 하며 이 도 필요합니다 에는 영역의 시작 부분에 대한 포인터와 이 영역의 크기가 필요합니다.지역 크기가 필요한 경우 해당 지역을 추적해야 합니다.
네, malloc() 실장은 보통 지역 크기를 추적하지만 간접적으로 이를 수행하거나 값을 반올림하거나 아예 유지하지 않을 수 있습니다.지원한다고 해도, 직접 추적하는 것에 비해, 이 방법으로 사이즈를 찾는 것은 늦어질 수 있습니다.
각 지역의 크기를 알 수 있는 데이터 구조가 필요한 경우 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 및 무료 통화만 교환하면 됩니다.다른 모든 포인터 조작에는 리팩터링이 필요하지 않습니다.
아니요, C 런타임 라이브러리는 이러한 기능을 제공하지 않습니다.
일부 라이브러리는 이 정보를 얻을 수 있는 플랫폼 또는 컴파일러 고유의 함수를 제공할 수 있지만 일반적으로 이 정보를 추적하는 방법은 다른 정수 변수입니다.
Quuxplusone은 다음과 같이 썼다.「이러한 보이드* 중 어느 쪽에서 온 것인지 포인터의 값으로 알 수 없는 한, 이러한 보이드*에서 동작할 수 있는 함수를 쓰는 것」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
사용방법:_msize
연결된 메모리에 대해서만 동작합니다.calloc
,malloc
의 되어 있는, Microsoft 의 메뉴얼에 되어 있는, 등.
크기를합니다.
calloc
,malloc
, 「」realloc
.
그렇지 않으면 예외를 범하게 될 거야
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/msize?view=vs-2019
malloc을 수 .
한편 OS API를 사용하여 Windows 힙 함수처럼 메모리를 동적으로 할당하면 가능합니다.
이게 당신의 구체적인 질문에 대한 답이 아니라는 걸 알지만, 하지만 고정관념에서 벗어나서 생각해보면...당신은 알 필요가 없을 것 같아요.좋아, 좋아, 내 말은 네가 잘못되거나 비정통적인 방식을 취했다는 뜻이 아니야즉, (코드를 확인하지 않고) 데이터가 할당된 메모리에 들어갈 수 있는지 알고 싶을 뿐입니다.그렇다면 이 솔루션이 더 나을 수 있습니다.오버헤드가 너무 커서는 안 되며, 실제로 이러한 문제를 다루고 있다면 "적합" 문제가 해결됩니다.
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);
끝장낼 수갑시다
나는 이것이 구현에 의존할 것으로 예상한다.
헤더 데이터 구조를 취득했을 경우는, 그것을 포인터에 캐스트 해 사이즈를 취득할 수 있습니다.
모두가 이미 말했듯:아니, 없어.
또, 벤더 고유의 기능은, 반드시 사용하지 말아 주세요.왜냐하면, 이러한 기능을 정말로 사용할 필요가 있는 경우는, 일반적으로 잘못 사용하고 있는 것을 알 수 있기 때문입니다.크기를 따로 저장하거나 전혀 알 필요가 없습니다.벤더 기능을 사용하는 것은 C로 쓰는 것의 주요 장점 중 하나인 휴대성을 잃는 가장 빠른 방법입니다.
이 코드는, 대부분의 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, 이 1, 1, 기억력 1이 .p
char*
.렇면면int*
4번으로 하다.
총 배분을 알 수 있는 방법은 없습니다.
쓸 수 하는 데 을 겪었습니다.strcat
★★★★★★★★★★★★★★★★★」strcpy
바로 합니다.
이 답변은 기술적인 답변은 아니지만 디버깅을 할 때 도움이 되는 만큼 도움이 될 수 있습니다.
쓰시는 .malloc
a d in a 로 dmemset
파라미터에 값알수하고, '알 수 malloc
.
다음과 같은 경우:
char* my_string = (char*) malloc(custom_size * sizeof(char));
if(my_string) { memset(my_string, 1, custom_size); }
그런 다음 할당된 메모리의 모양을 디버거에서 시각화할 수 있습니다.
언급URL : https://stackoverflow.com/questions/1281686/determine-size-of-dynamically-allocated-memory-in-c
'programing' 카테고리의 다른 글
VueJ - Vuex 상태가 업데이트될 때 구성 요소가 업데이트되지 않음 (0) | 2022.07.12 |
---|---|
"이진수 비트 연산자와 함께 부호 있는 정수 피연산자 사용" - 부호 없는 쇼트 사용 시 (0) | 2022.07.12 |
서블릿의 구조인스턴스화, 세션, 공유 변수 및 멀티스레딩 (0) | 2022.07.12 |
v-show에 표시된 후 입력에 초점을 맞춥니다. (0) | 2022.07.12 |
ES6 구문을 사용하여 vue에서 여러 구성 요소를 가져올 수 없음 (0) | 2022.07.11 |