什么((size_t*)ptr)[ - 1]在C中意味着什么?

Fir*_*zer 6 c size pointers

我想知道分配给指针的大小.

所以我找到了这个答案: 我怎么知道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;
}
Run Code Online (Sandbox Code Playgroud)

这条线(((size_t*)ptr)[-1])很完美,但我不明白为什么......

有人能帮我理解这条神奇的线条吗?谢谢!

Ian*_*ott 7

如果ptr是指向由分配的内存块malloc,calloc,realloc等等,然后(((size_t*)ptr)[-1]调用未定义的行为.我的猜测是它依赖于某个随机供应商的标准库实现的行为,恰好在返回的位置之前的位置存储了内存块的大小malloc.

不要使用这样的黑客!如果程序动态分配内存,它应该能够跟踪它分配的内存大小,而不依赖于未定义的行为.

实际分配的内存块malloc的大小可能大于请求的大小,因此您可能想知道已分配的块的实际大小,包括块末尾的多余内存.可移植代码不需要知道这一点,因为访问超出请求大小的位置也是未定义的行为,但是您可能想要了解这个大小是出于好奇或为了调试目的.

  • 在问题中显示的代码中,`p​​tr`不指向由`malloc`分配的内存块.例程`my_malloc`从`malloc`获取内存,存储大小,并返回指向内存的指针. (2认同)

uv_*_*uv_ -1

似乎编译器的 Cmalloc实现将分配的大小(以字节为单位)保留在返回地址之前的 4 个字节中。

通过将返回的地址 ( ptr) 转换为指向-的指针size_t(即((size_t*)ptr)),然后获取其前面的对齐地址(即 '[-1]',实际上只是指针算术 - 与写入相同*(((size_t*)ptr) - 1)) - 您可以访问分配的大小(类型size_t)。

这是为了解释它的((size_t*)ptr)[-1]含义以及它为何有效,但这绝不是使用它的建议。获取分配给指针的大小是应用程序代码要求的数量,如果需要,应该由应用程序代码管理,而不依赖于编译器实现。

  • 这个答案甚至没有解决问题。在该问题中,使用了用户例程“my_malloc”,而不是“malloc”,并且检查的大小是“my_malloc”存储的大小,而不是“malloc”存储的大小。 (4认同)
  • 抱歉,这个答案是不正确的。某些实现中的“malloc()”可能会以这种方式存储大小,但这绝不是“常见的”——肯定有一些实现不做这样的事情。这是 C 中形式上未定义的行为。 (2认同)
  • 这是一个可怕的答案。向读者解释**某些** C 实现可能会在块之前存储已分配块的大小是可以的,但是以“malloc”确实将大小保留在那里的不合格声明开头是可怕的。毫无条件地这么说是不正确的。此外,即使实现确实将大小存储在那里,也不意味着它支持通过“((size_t*)ptr)[-1]”访问它,这违反了标准 C 规则。 (2认同)