【问题标题】:C++ Call by Ref. with a dynamic sized struct without knowing its sizeC++ 参考调用。在不知道其大小的情况下使用动态大小的结构
【发布时间】:2012-01-29 13:53:33
【问题描述】:

我需要使用一个函数(API 的一部分),它使用引用调用将一些请求的数据存储到一个动态大小的结构中。该结构定义如下 - 它涉及 posix 或 NFS4 版本的访问控制列表,但这只是用例,我猜。

    typedef struct my_struct
    {
      unsigned int len;               /* total length of the struct in bytes */
      ...                             /* some other static sized fields */
      unsigned int version;           /* 2 different versions are possible */
      unsigned int amount;            /* number of entries that follow */
      union {
        entry_v1_t entry_v1[1];
        entry_v2_t entry_v2[1];
      }; 
    } my_struct_t;

条目有 2 个版本,我知道我将获得哪一个 (v1)。 entry_v1_tentry_v2_t 都是固定(但不同)大小的结构,只包含整数(所以我想它们不值得在这里解释)。现在我需要使用现有函数来使用引用调用所需的信息填充我的结构,签名如下,包括 cmets - 我无权访问实现:

    int get_information(char *pathname, void *ptr);

    /* The ptr parameter must point to a buffer mapped by the my_struct
     * structure. The first four bytes of the buffer must contain its total size.
     */

所以重点是,我必须为该结构分配内存,但不知道我必须分配多少条目(以及总大小)。你有遇到过这样的情况吗?

【问题讨论】:

  • API 期望调用者分配内存,即使调用者不知道要分配多少内存?这听起来不像是一个很棒的 AP​​I!
  • 这种模式在 Windows API 中并不少见,但总有一种机制可以查看先分配多少元素...
  • 让我检查一下是否还有机会获得条目数。我应该如何解释 entry_v1[ 1 ] ?它只是一种占位符,表示后面会有动态数量的条目吗?
  • @David: entry_v1[1] 只是表示长度为 1 的数组。它恰好经常用作“可变大小结构”技巧的一部分。
  • @01d55 :你确实误会了。 ;-] 这里使用的成语是在this blog post 中描述的。

标签: c++ struct buffer pass-by-reference


【解决方案1】:

好的,我知道它是如何工作的。感谢您的想法和笔记。我声明了一个my_struct 指针,并在动态数组=> 5 * sizeof(unsigned int) 之前为固定大小的字段(5) 分配了最小空间。使用该指针调用 get_information 会返回 -1 并设置 errno = 28strerror(errno) = "No space left on device"

但是,它将my_struct->len 字段设置为所需的大小,这似乎是我问题的答案 - 你应该怎么知道?不,我最初可以使用最小空间调用get_information,并计算出我需要分配多少空间,然后使用分配的正确大小的内存再次调用它以成功获取信息。

无论如何,循环解决方案似乎是有意义的,这将是我的下一次尝试 - 因为该动态数组中通常只有几个条目。

谢谢。

【讨论】:

    【解决方案2】:

    在 Windows API 下有很多这样的函数,你通常用一些 NULL 指针调用它们来获取缓冲区的大小,然后用分配的缓冲区再次调用。如果在下一次调用缓冲区大小发生变化时,函数返回错误,您需要再次分配。所以你在一个while循环中执行它,直到函数成功返回。

    所以你的 get_information 必须以某种方式实现这样的机制,如果缓冲区太小,它会返回 false,或者如果 ptr 为 NULL,则返回正确的大小。但这只是我的猜测。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-27
      • 2010-09-09
      • 1970-01-01
      • 2018-03-24
      • 2014-09-17
      相关资源
      最近更新 更多