确定在C中动态分配内存的大小

时间:2021-02-17 13:20:07

Is there a way in C to find out the size of dynamically allocated memory?

在C语言中是否存在一种方法来找出动态分配内存的大小?

For example, after

例如,在

char* p = malloc (100);

Is there a way to find out the size of memory associated with p?

有办法找出与p相关的内存大小吗?

15 个解决方案

#1


37  

comp.lang.c FAQ list · Question 7.27 -

comp.lang。·问题7.27 -

Q. So can I query the malloc package to find out how big an allocated block is?

问:那么我可以查询malloc包来找出分配的块有多大吗?

A. Unfortunately, there is no standard or portable way. (Some compilers provide nonstandard extensions.) If you need to know, you'll have to keep track of it yourself. (See also question 7.28.)

答:不幸的是,没有标准的或可移动的方式。(有些编译器提供非标准扩展。)如果你想知道,你就得自己记录下来。(见7.28还质疑。)

#2


38  

There is no standard way to find this information. However, some implementations provide functions like msize to do this. For example:

没有标准的方法可以找到这些信息。然而,有些实现提供了像msize这样的函数。例如:

Keep in mind though, that malloc will allocate a minimum of the size requested, so you should check if msize variant for your implementation actually returns the size of the object or the memory actually allocated on the heap.

但是请记住,malloc将分配所请求的最小大小,因此应该检查实现的msize变体是否实际返回对象的大小或实际分配到堆上的内存。

#3


8  

The C mentality is to provide the programmer with tools to help him with his job, not to provide abstractions which change the nature of his job. C also tries to avoid making things easier/safer if this happens at the expense of the performance limit.

C的心态是为程序员提供工具来帮助他完成工作,而不是提供那些改变工作性质的抽象。C也试图避免使事情变得更容易/更安全,如果这发生在性能限制的代价。

Certain things you might like to do with a region of memory only require the location of the start of the region. Such things include working with null-terminated strings, manipulating the first n bytes of the region (if the region is known to be at least this large), and so forth.

对于内存区域,您可能喜欢做的某些事情只需要该区域的开始位置。这些操作包括处理以null结尾的字符串、操作该区域的前n个字节(如果已知该区域至少有这么大),等等。

Basically, keeping track of the length of a region is extra work, and if C did it automatically, it would sometimes be doing it unnecessarily.

基本上,跟踪一个区域的长度是额外的工作,如果C自动做,它有时会做不必要的工作。

Many library functions (for instance fread()) require a pointer to the start of a region, and also the size of this region. If you need the size of a region, you must keep track of it.

许多库函数(例如fread())需要指向区域开始的指针,以及该区域的大小。如果您需要一个区域的大小,您必须跟踪它。

Yes, malloc() implementations usually keep track of a region's size, but they may do this indirectly, or round it up to some value, or not keep it at all. Even if they support it, finding the size this way might be slow compared with keeping track of it yourself.

是的,malloc()实现通常会跟踪一个区域的大小,但是它们可能会间接地这样做,或者将其四舍五入到某个值,或者根本不保留它。即使他们支持它,以这种方式找到大小可能比自己跟踪它要慢。

If you need a data structure that knows how big each region is, C can do that for you. Just use a struct that keeps track of how large the region is as well as a pointer to the region.

如果您需要一个数据结构,知道每个区域的大小,C可以为您做这些。只需使用一个结构体来跟踪该区域的大小,以及指向该区域的指针。

#4


6  

No, the C runtime library does not provide such a function.

不,C运行时库不提供这样的函数。

Some libraries may provide platform- or compiler-specific functions that can get this information, but generally the way to keep track of this information is in another integer variable.

有些库可能提供特定于平台或编译器的函数来获取这些信息,但是通常跟踪这些信息的方法是使用另一个整型变量。

#5


3  

Like everyone else already said: No there isn't.

就像其他人已经说过的:没有。

Also, I would always avoid all the vendor-specific functions here, because when you find that you really need to use them, that's generally a sign that you're doing it wrong. You should either store the size separately, or not have to know it at all. Using vendor functions is the quickest way to lose one of the main benefits of writing in C, portability.

此外,我总是避免使用所有特定于供应商的函数,因为当您发现确实需要使用它们时,这通常表明您做错了。您应该将大小分开存储,或者根本不需要知道它。使用供应商函数是最快失去用C编写的主要好处之一,即可移植性。

#6


2  

I would expect this to be implementation dependent.
If you got the header data structure, you could cast it back on the pointer and get the size.

我希望这是依赖于实现的。如果您获得了头数据结构,您可以将它转换回指针并获得大小。

#7


2  

This code will probably work on most Windows installations:

此代码可能适用于大多数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);
}

#8


2  

Here's the best way I've seen to create a tagged pointer to store the size with the address. All pointer functions would still work as expected:

这里是我看到的最好的方法来创建一个带标记的指针来存储地址的大小。所有指针函数仍将按预期工作:

Stolen from: https://*.com/a/35326444/638848

偷:https://*.com/a/35326444/638848

You could also implement a wrapper for malloc and free to add tags (like allocated size and other meta information) before the pointer returned by malloc. This is in fact the method that a c++ compiler tags objects with references to virtual classes. Here is one working example:

您还可以为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;
}

The advantage of this method over a structure with size and pointer

这种方法优于具有大小和指针的结构

 struct pointer
 {
   size_t size;
   void *p;
 };

is that you only need to replace the malloc and free calls. All other pointer operations require no refactoring.

您只需要替换malloc和免费调用。所有其他的指针操作都不需要重构。

#9


1  

No, there isn't.

不,没有。

#10


1  

If you use malloc then you can not get the size.

In the other hand, if you use OS API to dynamically allocate memory, like Windows heap functions, then it's possible to do that.

如果您使用malloc,那么您无法获得大小。另一方面,如果您使用OS API动态分配内存,比如Windows堆函数,那么就有可能这样做。

#11


1  

This may work, a small update in your code:

这可能有用,代码中的一个小更新:

void* inc = (void*) (++p)
size=p-inc;

But this will result 1, that is, memory associated with p if it is char*. If it is int* then result will be 4.

但这将导致1,也就是,如果是char*,则与p相关的内存。如果是int*,则结果是4。

There is no way to find out total allocation.

没有办法找到总分配。

#12


1  

Well now I know this is not answering your specific question, however thinking outside of the box as it were... It occurs to me you probably do not need to know. Ok, ok, no I don't mean your have a bad or un-orthodox implementation... I mean is that you probably (without looking at your code I am only guessing) you prbably only want to know if your data can fit in the allocated memory, if that is the case then this solution might be better. It should not offer too much overhead and will solve your "fitting" problem if that is indeed what you are handling:

好吧,现在我知道这并不能回答你的具体问题,不管你是怎么想的……我突然想到你可能不需要知道。好吧,好吧,不,我不是说你有一个坏的或非正统的实现……我的意思是,您可能(我没有查看您的代码,我只是猜测)您可能只想知道您的数据是否能够适合已分配的内存,如果是这样,那么这个解决方案可能会更好。它不应该提供太多的开销,并将解决您的“拟合”问题,如果这确实是您正在处理的:

if ( p != (tmp = realloc(p, required_size)) ) p = tmp;

or if you need to maintain the old contents:

或者如果你需要维护旧的内容:

if ( p != (tmp = realloc(p, required_size)) ) memcpy(tmp, p = tmp, required_size);

of course you could just use:

当然你可以用:

p = realloc(p, required_size);

and be done with it.

就这样吧。

#13


0  

Everyone telling you it's impossible is technically correct (the best kind of correct).

每个告诉你不可能的人在技术上都是正确的(最好的一种正确)。

For engineering reasons, it is a bad idea to rely on the malloc subsystem to tell you the size of an allocated block accurately. To convince yourself of this, imagine that you were writing a large application, with several different memory allocators — maybe you use raw libc malloc in one part, but C++ operator new in another part, and then some specific Windows API in yet another part. So you've got all kinds of void* flying around. Writing a function that can work on any of these void*s impossible, unless you can somehow tell from the pointer's value which of your heaps it came from.

由于工程上的原因,依赖malloc子系统来准确地告诉您分配的块的大小不是一个好主意。为了让您相信这一点,假设您正在编写一个大型应用程序,其中有几个不同的内存分配器—可能您在一个部分中使用了原始的libc malloc,但是在另一个部分中使用了c++操作符new,然后在另一个部分中使用了一些特定的Windows API。所以你有各种各样的空虚。编写一个可以处理任何这些void*的函数是不可能的,除非您可以从指针的值中知道它来自哪个堆。

So you might want to wrap up each pointer in your program with some convention that indicates where the pointer came from (and where it needs to be returned to). For example, in C++ we call that std::unique_ptr<void> (for pointers that need to be operator delete'd) or std::unique_ptr<void, D> (for pointers that need to be returned via some other mechanism D). You could do the same kind of thing in C if you wanted to. And once you're wrapping up pointers in bigger safer objects anyway, it's just a small step to struct SizedPtr { void *ptr; size_t size; } and then you never need to worry about the size of an allocation again.

因此,您可能希望在程序中使用一些约定来包装每个指针,该约定指示指针来自哪里(以及它需要返回到哪里)。例如,在c++中我们调用std::unique_ptr (对于需要操作符delete D的指针)或std::unique_ptr (对于需要通过其他机制D返回的指针)。一旦在更大的更安全的对象中结束指针,构造SizedPtr {void *ptr仅仅是一个小步骤;size_t大小;然后你就再也不用担心分配的大小了。 ,>

However.

然而。

There are also good reasons why you might legitimately want to know the actual underlying size of an allocation. For example, maybe you're writing a profiling tool for your app that will report the actual amount of memory used by each subsystem, not just the amount of memory that the programmer thought he was using. If each of your 10-byte allocations is secretly using 16 bytes under the hood, that's good to know! (Of course there will be other overhead as well, which you're not measuring this way. But there are yet other tools for that job.) Or maybe you're just investigating the behavior of realloc on your platform. Or maybe you'd like to "round up" the capacity of a growing allocation to avoid premature reallocations in the future. Example:

还有一些很好的理由可以解释为什么你可以合法地想知道一个分配的实际大小。例如,您可能正在为应用程序编写一个分析工具,该工具将报告每个子系统实际使用的内存数量,而不仅仅是程序员认为他正在使用的内存数量。如果每个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;
}

To get the size of the allocation behind a non-null pointer which has been returned directly from libc malloc — not from a custom heap, and not pointing into the middle of an object — you can use the following OS-specific APIs, which I have bundled up into a "portable-ish" wrapper function for convenience. If you find a common system where this code doesn't work, please leave a comment and I'll try to fix it!

得到分配的大小返回一个null指针已直接从背后libc malloc——不是从堆一个自定义的,而不是指向一个对象的中间,你可以使用以下os api,我捆绑成一个“portable-ish”包装器函数方便。如果您发现这个代码不工作的公共系统,请留下评论,我将尝试修复它!

#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);
}

Tested on:

测试:

  • Visual Studio, Win64 — _msize
  • Visual Studio, Win64 - _msize
  • GCC/Clang, glibc, Linux — malloc_usable_size
  • GCC/Clang, glibc, Linux - malloc_usable_size
  • Clang, libc, Mac OS X — malloc_size
  • Clang, libc, Mac OS X - malloc_size
  • Clang, jemalloc, Mac OS X — works in practice but I wouldn't trust it (silently mixes jemalloc's malloc and the native libc's malloc_size)
  • Clang, jemalloc, Mac OS X -在实践中有效,但我不相信它(将jemalloc的malloc和本地libc的malloc_size悄悄地混合)
  • Should work fine with jemalloc on Linux
  • 在Linux上使用jemalloc应该没问题吗?
  • Should work fine with dlmalloc on Linux if compiled without USE_DL_PREFIX
  • 如果不使用USE_DL_PREFIX编译,那么在Linux上使用dlmalloc是否可以正常工作
  • Should work fine with tcmalloc everywhere
  • tcmalloc在任何地方都可以正常工作吗

#14


-1  

int *a; a=malloc(n*sizeof(int)); if malloc returns NULL that means you did not get memory otherwise what you get is base address of assigned block, meaning (n*sizeof(int)) block size.

int *;一个= malloc(n * sizeof(int));如果malloc返回NULL,这意味着您没有得到内存,否则您将得到分配块的基地址,这意味着(n*sizeof(int)块大小。

#15


-4  

I am not sure but try:

我不确定,但试着:

char **q = &p;
int size = q[1] - q[0]; 

#1


37  

comp.lang.c FAQ list · Question 7.27 -

comp.lang。·问题7.27 -

Q. So can I query the malloc package to find out how big an allocated block is?

问:那么我可以查询malloc包来找出分配的块有多大吗?

A. Unfortunately, there is no standard or portable way. (Some compilers provide nonstandard extensions.) If you need to know, you'll have to keep track of it yourself. (See also question 7.28.)

答:不幸的是,没有标准的或可移动的方式。(有些编译器提供非标准扩展。)如果你想知道,你就得自己记录下来。(见7.28还质疑。)

#2


38  

There is no standard way to find this information. However, some implementations provide functions like msize to do this. For example:

没有标准的方法可以找到这些信息。然而,有些实现提供了像msize这样的函数。例如:

Keep in mind though, that malloc will allocate a minimum of the size requested, so you should check if msize variant for your implementation actually returns the size of the object or the memory actually allocated on the heap.

但是请记住,malloc将分配所请求的最小大小,因此应该检查实现的msize变体是否实际返回对象的大小或实际分配到堆上的内存。

#3


8  

The C mentality is to provide the programmer with tools to help him with his job, not to provide abstractions which change the nature of his job. C also tries to avoid making things easier/safer if this happens at the expense of the performance limit.

C的心态是为程序员提供工具来帮助他完成工作,而不是提供那些改变工作性质的抽象。C也试图避免使事情变得更容易/更安全,如果这发生在性能限制的代价。

Certain things you might like to do with a region of memory only require the location of the start of the region. Such things include working with null-terminated strings, manipulating the first n bytes of the region (if the region is known to be at least this large), and so forth.

对于内存区域,您可能喜欢做的某些事情只需要该区域的开始位置。这些操作包括处理以null结尾的字符串、操作该区域的前n个字节(如果已知该区域至少有这么大),等等。

Basically, keeping track of the length of a region is extra work, and if C did it automatically, it would sometimes be doing it unnecessarily.

基本上,跟踪一个区域的长度是额外的工作,如果C自动做,它有时会做不必要的工作。

Many library functions (for instance fread()) require a pointer to the start of a region, and also the size of this region. If you need the size of a region, you must keep track of it.

许多库函数(例如fread())需要指向区域开始的指针,以及该区域的大小。如果您需要一个区域的大小,您必须跟踪它。

Yes, malloc() implementations usually keep track of a region's size, but they may do this indirectly, or round it up to some value, or not keep it at all. Even if they support it, finding the size this way might be slow compared with keeping track of it yourself.

是的,malloc()实现通常会跟踪一个区域的大小,但是它们可能会间接地这样做,或者将其四舍五入到某个值,或者根本不保留它。即使他们支持它,以这种方式找到大小可能比自己跟踪它要慢。

If you need a data structure that knows how big each region is, C can do that for you. Just use a struct that keeps track of how large the region is as well as a pointer to the region.

如果您需要一个数据结构,知道每个区域的大小,C可以为您做这些。只需使用一个结构体来跟踪该区域的大小,以及指向该区域的指针。

#4


6  

No, the C runtime library does not provide such a function.

不,C运行时库不提供这样的函数。

Some libraries may provide platform- or compiler-specific functions that can get this information, but generally the way to keep track of this information is in another integer variable.

有些库可能提供特定于平台或编译器的函数来获取这些信息,但是通常跟踪这些信息的方法是使用另一个整型变量。

#5


3  

Like everyone else already said: No there isn't.

就像其他人已经说过的:没有。

Also, I would always avoid all the vendor-specific functions here, because when you find that you really need to use them, that's generally a sign that you're doing it wrong. You should either store the size separately, or not have to know it at all. Using vendor functions is the quickest way to lose one of the main benefits of writing in C, portability.

此外,我总是避免使用所有特定于供应商的函数,因为当您发现确实需要使用它们时,这通常表明您做错了。您应该将大小分开存储,或者根本不需要知道它。使用供应商函数是最快失去用C编写的主要好处之一,即可移植性。

#6


2  

I would expect this to be implementation dependent.
If you got the header data structure, you could cast it back on the pointer and get the size.

我希望这是依赖于实现的。如果您获得了头数据结构,您可以将它转换回指针并获得大小。

#7


2  

This code will probably work on most Windows installations:

此代码可能适用于大多数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);
}

#8


2  

Here's the best way I've seen to create a tagged pointer to store the size with the address. All pointer functions would still work as expected:

这里是我看到的最好的方法来创建一个带标记的指针来存储地址的大小。所有指针函数仍将按预期工作:

Stolen from: https://*.com/a/35326444/638848

偷:https://*.com/a/35326444/638848

You could also implement a wrapper for malloc and free to add tags (like allocated size and other meta information) before the pointer returned by malloc. This is in fact the method that a c++ compiler tags objects with references to virtual classes. Here is one working example:

您还可以为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;
}

The advantage of this method over a structure with size and pointer

这种方法优于具有大小和指针的结构

 struct pointer
 {
   size_t size;
   void *p;
 };

is that you only need to replace the malloc and free calls. All other pointer operations require no refactoring.

您只需要替换malloc和免费调用。所有其他的指针操作都不需要重构。

#9


1  

No, there isn't.

不,没有。

#10


1  

If you use malloc then you can not get the size.

In the other hand, if you use OS API to dynamically allocate memory, like Windows heap functions, then it's possible to do that.

如果您使用malloc,那么您无法获得大小。另一方面,如果您使用OS API动态分配内存,比如Windows堆函数,那么就有可能这样做。

#11


1  

This may work, a small update in your code:

这可能有用,代码中的一个小更新:

void* inc = (void*) (++p)
size=p-inc;

But this will result 1, that is, memory associated with p if it is char*. If it is int* then result will be 4.

但这将导致1,也就是,如果是char*,则与p相关的内存。如果是int*,则结果是4。

There is no way to find out total allocation.

没有办法找到总分配。

#12


1  

Well now I know this is not answering your specific question, however thinking outside of the box as it were... It occurs to me you probably do not need to know. Ok, ok, no I don't mean your have a bad or un-orthodox implementation... I mean is that you probably (without looking at your code I am only guessing) you prbably only want to know if your data can fit in the allocated memory, if that is the case then this solution might be better. It should not offer too much overhead and will solve your "fitting" problem if that is indeed what you are handling:

好吧,现在我知道这并不能回答你的具体问题,不管你是怎么想的……我突然想到你可能不需要知道。好吧,好吧,不,我不是说你有一个坏的或非正统的实现……我的意思是,您可能(我没有查看您的代码,我只是猜测)您可能只想知道您的数据是否能够适合已分配的内存,如果是这样,那么这个解决方案可能会更好。它不应该提供太多的开销,并将解决您的“拟合”问题,如果这确实是您正在处理的:

if ( p != (tmp = realloc(p, required_size)) ) p = tmp;

or if you need to maintain the old contents:

或者如果你需要维护旧的内容:

if ( p != (tmp = realloc(p, required_size)) ) memcpy(tmp, p = tmp, required_size);

of course you could just use:

当然你可以用:

p = realloc(p, required_size);

and be done with it.

就这样吧。

#13


0  

Everyone telling you it's impossible is technically correct (the best kind of correct).

每个告诉你不可能的人在技术上都是正确的(最好的一种正确)。

For engineering reasons, it is a bad idea to rely on the malloc subsystem to tell you the size of an allocated block accurately. To convince yourself of this, imagine that you were writing a large application, with several different memory allocators — maybe you use raw libc malloc in one part, but C++ operator new in another part, and then some specific Windows API in yet another part. So you've got all kinds of void* flying around. Writing a function that can work on any of these void*s impossible, unless you can somehow tell from the pointer's value which of your heaps it came from.

由于工程上的原因,依赖malloc子系统来准确地告诉您分配的块的大小不是一个好主意。为了让您相信这一点,假设您正在编写一个大型应用程序,其中有几个不同的内存分配器—可能您在一个部分中使用了原始的libc malloc,但是在另一个部分中使用了c++操作符new,然后在另一个部分中使用了一些特定的Windows API。所以你有各种各样的空虚。编写一个可以处理任何这些void*的函数是不可能的,除非您可以从指针的值中知道它来自哪个堆。

So you might want to wrap up each pointer in your program with some convention that indicates where the pointer came from (and where it needs to be returned to). For example, in C++ we call that std::unique_ptr<void> (for pointers that need to be operator delete'd) or std::unique_ptr<void, D> (for pointers that need to be returned via some other mechanism D). You could do the same kind of thing in C if you wanted to. And once you're wrapping up pointers in bigger safer objects anyway, it's just a small step to struct SizedPtr { void *ptr; size_t size; } and then you never need to worry about the size of an allocation again.

因此,您可能希望在程序中使用一些约定来包装每个指针,该约定指示指针来自哪里(以及它需要返回到哪里)。例如,在c++中我们调用std::unique_ptr (对于需要操作符delete D的指针)或std::unique_ptr (对于需要通过其他机制D返回的指针)。一旦在更大的更安全的对象中结束指针,构造SizedPtr {void *ptr仅仅是一个小步骤;size_t大小;然后你就再也不用担心分配的大小了。 ,>

However.

然而。

There are also good reasons why you might legitimately want to know the actual underlying size of an allocation. For example, maybe you're writing a profiling tool for your app that will report the actual amount of memory used by each subsystem, not just the amount of memory that the programmer thought he was using. If each of your 10-byte allocations is secretly using 16 bytes under the hood, that's good to know! (Of course there will be other overhead as well, which you're not measuring this way. But there are yet other tools for that job.) Or maybe you're just investigating the behavior of realloc on your platform. Or maybe you'd like to "round up" the capacity of a growing allocation to avoid premature reallocations in the future. Example:

还有一些很好的理由可以解释为什么你可以合法地想知道一个分配的实际大小。例如,您可能正在为应用程序编写一个分析工具,该工具将报告每个子系统实际使用的内存数量,而不仅仅是程序员认为他正在使用的内存数量。如果每个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;
}

To get the size of the allocation behind a non-null pointer which has been returned directly from libc malloc — not from a custom heap, and not pointing into the middle of an object — you can use the following OS-specific APIs, which I have bundled up into a "portable-ish" wrapper function for convenience. If you find a common system where this code doesn't work, please leave a comment and I'll try to fix it!

得到分配的大小返回一个null指针已直接从背后libc malloc——不是从堆一个自定义的,而不是指向一个对象的中间,你可以使用以下os api,我捆绑成一个“portable-ish”包装器函数方便。如果您发现这个代码不工作的公共系统,请留下评论,我将尝试修复它!

#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);
}

Tested on:

测试:

  • Visual Studio, Win64 — _msize
  • Visual Studio, Win64 - _msize
  • GCC/Clang, glibc, Linux — malloc_usable_size
  • GCC/Clang, glibc, Linux - malloc_usable_size
  • Clang, libc, Mac OS X — malloc_size
  • Clang, libc, Mac OS X - malloc_size
  • Clang, jemalloc, Mac OS X — works in practice but I wouldn't trust it (silently mixes jemalloc's malloc and the native libc's malloc_size)
  • Clang, jemalloc, Mac OS X -在实践中有效,但我不相信它(将jemalloc的malloc和本地libc的malloc_size悄悄地混合)
  • Should work fine with jemalloc on Linux
  • 在Linux上使用jemalloc应该没问题吗?
  • Should work fine with dlmalloc on Linux if compiled without USE_DL_PREFIX
  • 如果不使用USE_DL_PREFIX编译,那么在Linux上使用dlmalloc是否可以正常工作
  • Should work fine with tcmalloc everywhere
  • tcmalloc在任何地方都可以正常工作吗

#14


-1  

int *a; a=malloc(n*sizeof(int)); if malloc returns NULL that means you did not get memory otherwise what you get is base address of assigned block, meaning (n*sizeof(int)) block size.

int *;一个= malloc(n * sizeof(int));如果malloc返回NULL,这意味着您没有得到内存,否则您将得到分配块的基地址,这意味着(n*sizeof(int)块大小。

#15


-4  

I am not sure but try:

我不确定,但试着:

char **q = &p;
int size = q[1] - q[0];