【问题标题】:How to allocate memory for a struct with a member of unknown variable size?如何为具有未知变量大小的成员的结构分配内存?
【发布时间】:2021-04-05 18:53:32
【问题描述】:

几天前有人在另一个SO question 中帮助了我大部分内容。那个时候struct base的大小是提前知道的。我想将成员 path 更改为一个字符数组,其大小直到在为 base_new() 函数中的 base 的新实例分配内存之前才知道。

在以前的版本中,要求所有文件都存放在同一目录下,只添加文件名;并且长度限制为 256。现在我想允许用户在../../databases 目录下添加子目录,并且不限制长度。

是否可以在base_new()中的db[i] = malloc( sizeof ( struct base ) )之前或之后设置path的大小?

或者,也许,我应该简单地问一下,这如何实现?

谢谢。

/* Global declaration */
struct base {
 ...
 char path[];
};

struct base **db;

/* in main() */
db = malloc( n * sizeof *db );
for (size_t i = 0; i < n; ++i)
  db[i] = NULL;

/* Function to assign pointer db[i] to newly allocated struct base */
int base_new( void )
{
  /* declarations */
  // Assign pointer to beginning of memory allocation for the new instance of struct base.
  if ( ( db[i] = malloc( sizeof ( struct base ) ) ) == NULL )
    {
      printf( "Error attempting to malloc space for new base.\n" );
      return 1;
    }

  // When size of path was fixed, just truncated name to 256. */
  l = sizeof( db[i]->path );
  rc = snprintf( db[i]->path, l, "%s%.*s", "../../databases/", 256, name );
  if ( rc > l - 1 || rc < 0 )
    {
      // Not enough space; truncate and add the '\0' at l.
      db[i]->path[l] = '\0';
    }  

  // When size of path variable and writing path. */
  l = sizeof( db[i]->path ) - 16;
  rc = snprintf( db[i]->path, l, "%s%s", "../../databases/", path );
  if ( rc > l - 1 || rc < 0 )
    {
      
      db[i]->path[l] = '\0';
    }  

}

我在问题顶部收到一条消息,询问现有问题是否回答了这个问题。它密切相关且很有帮助,但我认为我在这里收到的答案更好,并讨论了其他一些相关点。我不知道它应该如何工作,但我选择了否,因为这个答案更好,或者至少我可以更好地理解它。这个答案显示了如何 malloc 结构的变量成员,并讨论了在释放指向结构的指针之前按成员释放结构的内存。另一个问题更笼统,但仍然有帮助。谢谢。

【问题讨论】:

  • 这能回答你的问题吗? Array of variable length in struct
  • 您可以使用上述重复帖子中所述的灵活数组成员进行单次分配,或者您可以将path更改为char *并分配path 与第二个 malloc 通话。
  • @kaylum 是的,这很有帮助。谢谢你。我对结构是什么有点困惑,因为它的所有成员现在都是指针。它本身并不占用太多数据,并且它的所有成员都可以分配到任何可用的地方。它是一个有组织的指针集合,指向杂乱无章的内存块。

标签: c struct dynamic-memory-allocation


【解决方案1】:

您可以在结构中使用指针来代替数组:

struct base {
    ...
    char *path;
};

稍后,在需要时为该指针分配内存:

base.path = malloc(n * sizeof(char)); // n is the variable size you will set before

由于您现在动态分配内存,请不要忘记free 以避免任何内存泄漏。在 C 中,要求每个结构都具有固定的字节长度,因此,例如,sizeof(struct base) 可以在编译时进行评估。在您的情况下,可变长度数组的大小无法在编译时确定,因此在编译时不知道 char path[l] 之类的操作是非法的。

顺便说一句,关于

的更正
l = sizeof( db[i]->path );

首先,即使path 被声明为一个数组,这也不会给出它的长度大小,它会返回数组占用的完整字节大小,你必须除以通过sizeof (char) 获取长度。但是,既然您已将其声明为指针,我想您实际上并不需要这样做。

【讨论】:

  • 谢谢。 free( db[i] ) 是否也会为 base.path 释放单独的 malloc,或者是否需要分别释放两个 malloc 语句?
  • 您应该首先free 成员,例如free(db[i]-&gt;path),然后是各个结构。
  • 关于确定数组长度的最后一部分是有道理的,但我不明白。在以前的版本中,path 被声明为char[285],我使用100 对其进行了修改,以查看它是否会截断名称,并且它会在 100 是 100 个字符的地方进行。那为什么会这样呢?
  • 我在snprintf 中使用了它,因为我严重滥用了它,@dxiv 在回答结束时帮助了我here
  • 我正在使用 minGW-W64 并且 sizeof(char) 返回 1。这不是典型的还是编译器不同?谢谢。
猜你喜欢
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
相关资源
最近更新 更多