首页 > 解决方案 > 对指针和内存池分配的误解

问题描述

我很难理解下面代码的正确实现。我正在尝试实现一个非常基本的内存池,并让用户能够从池中“创建”对象。

与“buf”进行联合的一个目标/目标是能够轻松地从字节流中海化或读取原始消息。

#include <stdio.h>
#include <stdint.h>
// This is the object that everyone will create/use
struct Msg {
  union {
    // Unique msg id for users to do something based on id
    uint16_t msg_type;
    // Data right now is a fixed length of 8 bytes but if I wanted to 
    // change this requirement I could easily since we are allocating 
    // from a memory pool
    uint8_t* data;
  };
  // This is the pointer to the next spot in the memory pool.
  uint8_t* buf;
};

int main() {
  uint8_t memory_pool[100];
  // Somewhere in user code
  struct Msg* msg_ptr;
  // This doesnt work! Throws a seg fault.
  msg_ptr->buf = &memory_pool[0];
  // I thought by setting where buf points to I could something like
  msg_ptr->msg_id = 1234;
  msg_ptr->data[0] = 100;
  // And so on
  // The real implementation would have the user call something like below, where
  // my_memory_pool_get would assign 'buf' to the next available spot in the memory_pool
  my_memory_pool_get(msg_ptr)
  
  // Now if I make Msg.msg_id a pointer to a 16 bit int
  // uint16_t* msg_id
  // The above code works just have to do something like:
  struct Msg msg;
  msg.buf = &memory_pool[0];
  *msg.msg_id = 1234;
  if (*msg.msg_id == 1234) { }
}
  
  

标签: cpointers

解决方案


您尚未为 msg_ptr 分配任何内存,因此当您访问msg_ptr->buf时它当然会崩溃,因为 msg_ptr 是指向内存中尚未分配的某个对象的指针。

struct Msg* msg_ptr; 
// This doesnt work! Throws a seg fault.
msg_ptr->buf = &memory_pool[0];  

以下不会崩溃,因为 msg 不是指针。味精在堆栈上分配。

// Now if I make Msg.msg_id a pointer to a 16 bit int
// uint16_t* msg_id
// The above code works just have to do something like:
struct Msg msg;
msg.buf = &memory_pool[0];
*msg.msg_id = 1234;
if (*msg.msg_id == 1234) { }

您可能希望将函数my_memory_pool_get(msg_ptr)编写为:

Msg* my_memory_pool_get(){
    int offset = 0;

    // Calculate the position/offset and make sure there is room!
    int room = ... // figure out how to determine is there is room in the buffer.
    if (!room)
        return NULL;

    return &memory_pool[offset];
}

推荐阅读