V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Huelse
V2EX  ›  C++

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

  •  
  •   Huelse · 2020-01-05 18:10:34 +08:00 · 6046 次点击
    这是一个创建于 1783 天前的主题,其中的信息可能已经有所发展或是发生改变。

    情况如下:

    #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

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

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

    非常感谢!

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

    一个经典的内存分配算法是 https://en.wikipedia.org/wiki/Buddy_memory_allocation
    FrankHB
        11
    FrankHB  
       2020-01-06 03:56:41 +08:00
    @hobochen C2x 都快出来了还 2011,,,
    ……嘛,N1570 以后的 draft 和正式出版的太接近的得要密码(
    FrankHB
        12
    FrankHB  
       2020-01-06 03:58:41 +08:00
    ……哦这个是 C 艹么。
    送 LZ 一句话:
    “恁也配用 new ?”
    理解好了再倒腾,对谁都好,谢谢合作。
    lomewcl
        13
    lomewcl  
       2020-01-06 06:17:44 +08:00   ❤️ 1
    不是很清楚 malloc 族相关的函数能不能用到 new 上,懒得查了。
    堆分配的内存以 chunk 为最小单位,涉及对齐等,比申请的空间大一点是很正常的。
    geelaw
        14
    geelaw  
       2020-01-06 06:53:40 +08:00 via iPhone
    @FrankHB #12 楼主这个 malloc_usable_size 都不是 C 或者 C++ 的一部分(
    augustheart
        15
    augustheart  
       2020-01-06 09:34:32 +08:00   ❤️ 1
    不要去计算堆内存,虽然其实有些方法可以,但是不可靠,不能得到精确的内存。因为 c 分配内存的时候就不会严格按照申请的长度分配,会有等于指针长度的对齐。
    另外,c 的数组后面是有 0 占位的,配合上对齐的效果,所以会出现 size + 1 的情况(不能理解的话就过吧,不搞逆向的话不需要理解这种细节,因为不能靠这个写代码,会出人命的)
    FrankHB
        16
    FrankHB  
       2020-01-06 20:44:42 +08:00
    @lomewcl 不用查了,都没给 main,甚至都没说是完整的翻译单元,那至少能用重定义::operator new 的方式可移植地保证始终不正确。
    FrankHB
        17
    FrankHB  
       2020-01-06 20:45:10 +08:00
    ::operator new→::operator new[]。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2792 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:51 · PVG 19:51 · LAX 03:51 · JFK 06:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.