Joe*_*oel 66 c malloc pointers memory-management
我已经分配了一个像这样mystruct大小的"数组" n:
if (NULL == (p = calloc(sizeof(struct mystruct) * n,1))) {
 /* handle error */
}
后来,我只能访问p,不再拥有n.有没有办法只给出指针确定数组的长度p?
我认为它必须是可能的,因为free(p)就是这样.我知道malloc()它记录了它分配了多少内存,这就是它知道长度的原因; 也许有办法查询这些信息?就像是...
int length = askMallocLibraryHowMuchMemoryWasAlloced(p) / sizeof(mystruct)
我知道我应该修改代码,以便我知道n,但如果可能,我宁愿不这样做.有任何想法吗?
Bar*_*ark 52
不,如果不强烈依赖于实施细节,就无法获得这些信息malloc.特别是,malloc可以分配比您请求更多的字节(例如,为了特定存储器架构中的效率).重新设计代码会更好,以便您n明确地跟踪.替代方案至少是重新设计和更危险的方法(鉴于它是非标准的,滥用指针的语义,对于那些n追随你的人来说将是一个维护噩梦):将长度保存在malloc'd地址,后跟数组.分配将是:
void *p = calloc(sizeof(struct mystruct) * n + sizeof(unsigned long int),1));
*((unsigned long int*)p) = n;
n现在存储在*((unsigned long int*)p)数组中,现在是数组的开头
void *arr = p+sizeof(unsigned long int);
编辑:只是为了扮演魔鬼的拥护者......我知道这些"解决方案"都需要重新设计,但让我们来解决它.当然,上面介绍的解决方案只是一个(包装好的)结构的hacky实现.你不妨定义:
typedef struct { 
  unsigned int n;
  void *arr;
} arrInfo;
传递arrInfos而不是原始指针.
现在我们正在做饭.但只要你重新设计,为什么要停在这里?你真正想要的是一个抽象数据类型(ADT).任何算法和数据结构类的介绍性文本都可以.ADT定义数据类型的公共接口,但隐藏该数据类型的实现.因此,公开的阵列的ADT可能看起来像
typedef void* arrayInfo;
(arrayInfo)newArrayInfo(unsignd int n, unsigned int itemSize);
(void)deleteArrayInfo(arrayInfo);
(unsigned int)arrayLength(arrayInfo);
(void*)arrayPtr(arrayInfo);
...
换句话说,ADT是数据和行为封装的一种形式......换句话说,它与使用直接C的面向对象编程一样接近.除非你被困在没有的平台上有一个C++编译器,你也可以全力以赴,只使用STL std::vector.
在那里,我们采用了一个关于C的简单问题,最终得到了C++.上帝帮助我们所有人.
只是为了确认以前的答案:通过研究一个指针,没有办法知道返回这个指针的malloc分配了多少内存.
这是不可能的原因之一.让我们假设一个带有假设函数的代码叫做get_size(void*),它返回为指针分配的内存:
typedef struct MyStructTag
{ /* etc. */ } MyStruct ;
void doSomething(MyStruct * p)
{
   /* well... extract the memory allocated? */
   size_t i = get_size(p) ;
   initializeMyStructArray(p, i) ;
}
void doSomethingElse()
{
   MyStruct * s = malloc(sizeof(MyStruct) * 10) ; /* Allocate 10 items */
   doSomething(s) ;
}
但是这种方法的问题在于,在C中,你可以使用指针算术.让我们重写doSomethingElse():
void doSomethingElse()
{
   MyStruct * s = malloc(sizeof(MyStruct) * 10) ; /* Allocate 10 items */
   MyStruct * s2 = s + 5 ; /* s2 points to the 5th item */
   doSomething(s2) ; /* Oops */
}
get_size如何工作,因为你向函数发送了一个有效的指针,但不是malloc返回的指针.即使get_size经历了查找大小的所有麻烦(即以低效的方式),在这种情况下,它将返回一个在您的上下文中可能出错的值.
总有办法避免这个问题,而在C语言中,你总是可以编写自己的分配器,但是,当你只需要记住分配了多少内存时,可能会遇到太麻烦.