C中具有自引用结构的存储器架构

时间:2017-12-29 17:44:45

标签: c memory-management self-reference

我有一个名为container的结构 这个结构有一个名为obj_mem的void类型的指针,它将指向一些已分配的内存 由于此内存必须能够保存不同的结构,因此我会跟踪地址及其包含的每个元素的类型(adress_objtype_obj)以进行访问和转换。
我的container结构的最后一个属性是它具有自引用child 因此,在运行时,用户可以创建容器的子项并向其添加对象。

typedef enum tob{ //type of object
   obj1, obj2, obj3, obj4 ...
}t_tob;

typedef struct obj1{
   //declare some stuff
}t_obj1;

typedef struct obj2{
   //declare some stuff
}t_obj2;

typedef struct obj3{
   //declare some stuff
}t_obj3;

typedef struct obj4{
   //declare some stuff
}t_obj4;

typedef struct container{
    int                name_size;
    char*              name;
    int                nmbr_obj;
    t_tob*             type_obj;
    char*              adress_obj;
    void*              mem_obj;
    int                nmbr_child;
    struct container*  child;
}t_container;

然后我有一个处理整个数据的功能:
   它处理容器obj_mem中的对象    然后迭代他的孩子并处理他们的对象。
   然后迭代他的孩子的孩子并处理他们的孩子    对象
   等......直到树的尽头。

问题:
我对编程很陌生,我不确定这是做正确的方法。
这段代码会导致很多malloc调用,所以内存不会连续,这是一个问题吗? 有没有更优雅的方式来做这种动态类型的事情?
你有什么书可以帮助我学习更多关于这种记忆架构的知识吗? 如果这篇文章看起来有点模糊,我很抱歉,这就是我现在的感受。

感谢你们。

2 个答案:

答案 0 :(得分:1)

如果您的容器必须保存数据树,那么某种形式的结构非常需要。真正看起来奇怪的一件事是你的对象成员类型是一个指针,通常是一个简单的值。

答案 1 :(得分:1)

  

记忆不会连续,这是一个问题吗?

它不是问题,但会影响性能。

使用更好的内存局部性(连续内存而不是碎片内存)有助于CPU利用它的缓存并最大限度地减少缓存未命中,这对于性能而言可能是一件非常重要的事情。

但这并不是最重要的部分。您可以稍后对此进行优化。最重要的部分是数据结构实际上做了它需要做的事情。

  

有没有更优雅的方式来做这种动态类型的事情?

可能,但我不确定你想做什么,所以我无法帮助你。

通常在编写动态类型系统时,对象的类型是对象的一部分,即:

struct my_object_s {
   unsigned int type;
   /* common type data*/
   struct vtable_s * vtable;
};

struct my_string_s {
   struct my_object_s header;
   size_t len;
   char str[];
}

这允许对象独立于其容器。

  

你有什么书可以帮助我学习更多关于这种内存架构的知识吗?

我在互联网上阅读了大部分我所知道的内容(我确实有几本书,但其中很少都是硬件架构)。

编辑(回答评论)

您可以找到有关使用C here的面向对象编程的更全面的信息。作者已经做了大量的工作来解释这些概念,并且在创作动态类型时经常使用(部分或全部)相同的想法。

例如,通过使用虚函数表,可以完全避免转换。

另一方面,当你有一组有限的类型时,使用switch语句是很常见的。

enum my_type_enum {
  /** A simple flag object object (`my_object_s`) for NULL. */
  MY_NULL,
  /** A simple flag  object (`my_object_s`) for OK. */
  MY_OK,
  /** A simple flag object (`my_err_s`) that indicates an error. */
  MY_ERR,
  /** A Number object object (`my_number_s`). */
  MY_NUMBER,
  /** A String object (`my_string_s`). */
  MY_STRING,
  /** An Array object object (`my_array_s`). */
  MY_ARRAY,
};

typedef struct { enum my_type_enum type; } my_object_s;

typedef struct {
  my_object_s header;
  size_t len;
  char str[];
} my_string_s;

void example_usage(my_object_s *obj) {
  switch (obj->type) {
  case MY_STRING:
    printf("String: %s", ((my_string_s *)obj)->str);
    break;
  default:
    printf("whatever...");
  }
}

请注意,通过将my_object_s作为每个类型的标头,您可以安全地访问标头数据,就像任何指向对象的指针是my_object_s *一样,这样您就可以识别它#39;基础类型。