关于 c++指针数组长度的问题

2020-01-05 18:10:34 +08:00
 Huelse

情况如下:

#include <malloc.h>

int size = 7;
double *a = new double[size];
cout << malloc_usable_size(a) / sizeof(*a) << endl;
//输出结果为 7

int size = 8;
double *a = new double[size];
cout << malloc_usable_size(a) / sizeof(*a) << endl;
//输出结果为 9

//sizeof(a)=sizeof(*a)=sizeof(double)=8

当 size=8 或 1024 其他偶数时,malloc_usable_size 会多一个 size

也就是数组长度为偶数情况下输出结果会比实际的加 1

我想问下这个要怎么处理才始终正确?

或者有没有其他更好的获取指针数组长度的方法?

非常感谢!

6047 次点击
所在节点    C++
17 条回复
codehz
2020-01-05 18:16:39 +08:00
答案是不能获得长度(
你必须用个变量去记录
inhzus
2020-01-05 18:43:27 +08:00
malloc_usable_size() returns the number of bytes available in the dynamically allocated buffer ptr, which may be greater than the requested size (but is guaranteed to be at least as large, if the request was successful). Typically, you should store the requested allocation size rather than use this function.

这个函数的文档有提到这点的。建议使用一个函数最好看看官方文档的~

回到获取指针指向数组的长度这个问题,是不能直接得到的(有什么奇技淫巧就不晓得了)。建议用 std::array 或 std::vector
Huelse
2020-01-05 18:55:00 +08:00
@codehz #1
@inhzus #2
猜到了这个结果,谢谢你们的回答
crclz
2020-01-05 20:36:00 +08:00
c 语言是设计的很简练的语言,它是个人设计的,并非组织设计的。c 语言很多地方按照约定来设计的,可能在主力语言是 java 或者 c#的人看来比较不美,但是实际上这是简洁的美。
例如:字符串以'\0'结尾。与字符串操作相关的库函数也都是基于这个假设。
再例如,库函数、变量命名都有大量缩写,例如 getchar, fopen,而不是 OpenFile()这种风格。
而数组的约定,就是将数组与指针等同起来理解。如果需要记录长度,请单独拿一个变量。
hobochen
2020-01-05 20:40:12 +08:00
@crclz ISO/IEC 9899:2011 心里一句 你知道我有多努力吗
crclz
2020-01-05 20:44:48 +08:00
@hobochen c 语言是个人设计的而非组织设计的,这句话(大意),我是从《深入理解计算机原理》里面看来的。
leido
2020-01-05 20:49:30 +08:00
哪本书告诉你堆内存可以这样算空间??
栈上才可以,前提是在申请栈空间的函数内
laminux29
2020-01-05 22:13:40 +08:00
老哥是 Java 用多了吧...就算 malloc_usable_size 这函数能给出正确的结果,万一编译器把它当函数来编译,那么它的性能也有可能比自己用变量记录慢得多啊。
dacapoday
2020-01-05 22:16:47 +08:00
@crclz 缩写这个是时代所限,早期的编译器不支持超过 8 位的 token。
ipwx
2020-01-05 22:24:28 +08:00
谁说你申请多少内存,malloc 就一定划多少内存给你的?为了解决内存碎片,malloc 很可能以一定程度地牺牲内存为代价,给你划一块稍微大一点但是不至于引起内存碎片的内存给你。

一个经典的内存分配算法是 https://en.wikipedia.org/wiki/Buddy_memory_allocation
FrankHB
2020-01-06 03:56:41 +08:00
@hobochen C2x 都快出来了还 2011,,,
……嘛,N1570 以后的 draft 和正式出版的太接近的得要密码(
FrankHB
2020-01-06 03:58:41 +08:00
……哦这个是 C 艹么。
送 LZ 一句话:
“恁也配用 new ?”
理解好了再倒腾,对谁都好,谢谢合作。
lomewcl
2020-01-06 06:17:44 +08:00
不是很清楚 malloc 族相关的函数能不能用到 new 上,懒得查了。
堆分配的内存以 chunk 为最小单位,涉及对齐等,比申请的空间大一点是很正常的。
geelaw
2020-01-06 06:53:40 +08:00
@FrankHB #12 楼主这个 malloc_usable_size 都不是 C 或者 C++ 的一部分(
augustheart
2020-01-06 09:34:32 +08:00
不要去计算堆内存,虽然其实有些方法可以,但是不可靠,不能得到精确的内存。因为 c 分配内存的时候就不会严格按照申请的长度分配,会有等于指针长度的对齐。
另外,c 的数组后面是有 0 占位的,配合上对齐的效果,所以会出现 size + 1 的情况(不能理解的话就过吧,不搞逆向的话不需要理解这种细节,因为不能靠这个写代码,会出人命的)
FrankHB
2020-01-06 20:44:42 +08:00
@lomewcl 不用查了,都没给 main,甚至都没说是完整的翻译单元,那至少能用重定义::operator new 的方式可移植地保证始终不正确。
FrankHB
2020-01-06 20:45:10 +08:00
::operator new→::operator new[]。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/635256

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX