代码之家  ›  专栏  ›  技术社区  ›  FL4SOF

为列表节点分配内存的安全方法

  •  3
  • FL4SOF  · 技术社区  · 16 年前

    在简单列表中,例如:

    struct Node {  
        Node *next;  
        void *data;  
    }  
    

    Node * t = (Node*)malloc(sizeof(Node) + DataSize));  
    

    并始终在分配的块末尾分配数据,

    t->data = (BYTE*)t+ sizeof(Node); /* BYTE is byte length, can use char in gcc */
    

    节点和数据将在一次运行中被删除,因此它们之间的耦合(按设计)没有真正的问题

    我在寻找可移植性问题(特别是包装)或其他未知的问题?

    这种分配方式安全且便于携带吗?

    4 回复  |  直到 16 年前
        1
  •  4
  •   unwind    16 年前

    正如他所说的,不要以假乱真 malloc() 在C语言中,这样做是无用的,并且可以隐藏错误。

    另外,要计算节点头后面的地址,我发现这样做更简单:

    t->data = t + 1;
    

    这是因为 t sizeof (Node) 在这种情况下。我发现这种用法在这个特殊的情况下是惯用的,即计算紧跟在某个东西后面的地址 malloc() ed(当“something”是一个具有静态已知大小的定义良好的类型时,如 Node 当然,在本例中是struct)。

    这有以下好处:

    • 类型名称不能重复。
    • sizeof ,那么短。
    • 非常简单的算法,容易阅读。

    我意识到你在使用

    /* This introduces the type name "Node", as an alias for an undefined struct. */
    typedef struct Node Node;
    
    struct Node {
      Node *next; /* This is OK, the compiler only needs to know size of pointer. */
      void *data;
    };
    

    Node * node_new(size_t n)
    {
      Node *node;
    
      if((node = malloc(sizeof *node + n)) != NULL)
      {
        node->next = NULL;
        node->data = node + 1;
      }
      return node;
    }
    

    就这样。注意使用 指针目标 malloc()

        2
  •  3
  •   MSalters    16 年前

    t+1 也对齐。可能,但不能保证。

        3
  •  2
  •   dirkgently    16 年前

    你不能使用 Node 直到创建别名。用途:

    typedef struct Node {
       struct Node* n;
       void* data;
    }Node;
    

    不需要把结果 malloc 如果你打算坚持使用C编译器。我发现以下内容更易于维护和阅读:

    Node* t = malloc(sizeof *t + DataSize);
    

    BYTE 不是语言定义的标准类型,因此 不受欢迎的 . 下面这一行的目的是什么?

    t->data = (BYTE*)t+ sizeof(Node); 
    

    如果你想分配一些东西,以下就足够了:

    t->data = pointer to some data ...
    

    如果要获取字节偏移量,请使用 offsetof 宏。

    此外,您可能需要 head 对象,它维护有关列表(长度等)的一些内务管理信息。

        4
  •  1
  •   aib    14 年前

    我同意@MSalters。只要你有一定程度的间接性 data 指针),您不妨做正确的事情并为它分配一个单独的块。

    现在,另一种选择是使用 灵活数组成员

    typedef struct Node {
        struct Node *next;
        char data[];
    } Node;
    
    Node *n = malloc(sizeof(*n) + DataSize * sizeof(*data));
    //if (n != NULL), access data[0 ~ DataSize-1]
    

    sizeof(struct Node) 添加适量的填料(如有),以满足 数据 data[] 就好像它被声明为一个最大可能大小的数组,可以容纳 malloc() . 这适用于所有类型的 数据 ,不仅仅是 char sizeof ).