首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在brk冻结自己的Malloc实施

在brk冻结自己的Malloc实施
EN

Stack Overflow用户
提问于 2020-04-29 22:24:56
回答 1查看 310关注 0票数 1

作为实践,我目前正在尝试用c编写我自己的malloc函数,所以我的问题是,在从堆中分配了一些之后,我的程序将冻结。我找到了代码段,它会导致冻结,当我调用brk sys调用时,它会冻结。我试着打开我的互斥锁,但这不起作用。为了测试它,我编写了一个永久循环,并在数组中分配内存并随机释放它。

代码语言:javascript
复制
static list *head = NULL;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

typedef struct list
{         
  size_t size_;                
  int free_;                  
  struct list *next_;      
  struct list *previouse_;
} block;

void blockAdd(block *href, size_t size)
{
  href->free_ = FALSE;
  href->next_ = NULL;
  href->previouse_ = NULL;

  if (!head || head > href)
  {
    if (head)
    {
      head->previouse_ = href;
    }
    href->size_ = size + sizeof(block);
    href->next_ = head;
    head = href;
  }
  else
  {
    href->next_ = NULL;
    block *current = head;

    while (current->next_ && current->next_ < href)
    {
      current = current->next_;
    }
    href->size_ = size + sizeof(block);
    href->next_ = current->next_;
    href->previouse_ = current;
    current->next_ = href;
  }
}

void *findExactSizeMatch(size_t size)
{
  block *href = head;
  size_t t = size + sizeof(block);

  while (href)
  {
    if (href->size_ == (size + sizeof(block)) && href->free_)
    {
      href->free_ = FALSE;
      return href;
    }
    href = href->next_;
  }
  return NULL;
}

void *findLagerBlock(size_t size)
{
  block *href = head;

  while (href)
  {
    if (href->free_ && href->size_ > size)
    {
      return split(href, size);
    }
    href = href->next_;
  }

  return NULL;
}

void *allocateMemory(size_t size)
{
  block *new_block = sbrk(BLOCK_SIZE(size));

  if (new_block == SBRK_FAILED)
  {
    exit(1);
  }
  blockAdd(new_block, size);

  return new_block;
}

bool checkAllFree()
{
  block *href = head;

  while (href)
  {
    if (!href->free_)
    {
      return FALSE;
    }
    href = href->next_;
  }
  return TRUE;
}

void freeList(block *ptr)
{
  if (checkAllFree())
  {
    if (brk(ptr) == BRK_FAILED)
    {
     exit(1);
    }
    head = NULL;
  }
}

void merge()
{
  block *href = head;

  while (href && href->next_)
  {
    if (href->free_ && href->next_->free_)
    {
      href->size_ = href->next_->size_;
      href->next_ = href->next_->next_;
    }
    href = href->next_;
  }
}

//--------------------------Here it makes some strange things
shrinkHeap()
{
  block *href = head;

  while (href && href->next_)
  {
    href = href->next_;
  }

  if (href && href->free_)
  {
    if (brk(href) == BRK_FAILED)
    {
      exit(1);
    }
    href->previouse_->next_ = href->next_;
  }
}

void *malloc(size_t size)
{
  if (!size)
  {
    return NULL;
  }
  pthread_mutex_lock(&mutex);

  block *new_list = NULL;

  new_list = findExactSizeMatch(size);
  if (new_list)
  {
    pthread_mutex_unlock(&mutex);
    return new_list + sizeof(block);
  }

  new_list = allocateMemory(size);
  pthread_mutex_unlock(&mutex);

  return new_list + sizeof(block);
}

void free(void *ptr)
{
  if (!ptr || !head)
  {
    return;
  }
  pthread_mutex_lock(&mutex);

  block *pref = ptr - sizeof(block);

  pref->free_ = TRUE;

  freeList(pref);
  shrinkHeap();
  merge();

  pthread_mutex_unlock(&mutex);
}

我不知道为什么但是brk冻结了我的程序。

谢谢你的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-30 08:30:16

代码中存在多个问题:

如果branch.

  • findLagerSize中的href->next_不是NULL,则不能更新href->next_->previouse_,并且应该使用size + sizeof(block)来定位适当的memory.

  • allocateMemory块。传递给sbrk的大小应该包括sizeof(block)额外的字节,这样分配的块如果大于size + sizeof(block).

  • in freeList则应该插入并拆分,如果checkAllFree()返回true,则应该调用brk(head),不是brk(ptr).

  • in merge,而是没有正确地更新href->size:您应该组合大小。此外,您不需要更新href-_next->previouse_.

  • The原型,因为shrinkHeap应该有一个返回类型和一个参数列表:

shrinkHeap(void)

  • In shrinkHeap您必须在调用brk之前更新链接,因为指针在调用后可能变得无效。此外,必须测试href->previouse_是否不是NULL,并且可以将此更新简化为:

如果(href->previouse_ != NULL) href->previouse_->next_ =NULL;

  • 您的malloc函数有一个缺陷:return new_list + sizeof(block);没有返回指向分配块的指针,而是返回一个更远的地方,从而导致应用程序写入超出分配块末尾的位置,从而可能破坏舞台。此外,由空闲计算的指针不指向block,即使程序没有写入内存块并调用未定义的行为,也会导致竞技场的进一步损坏。

malloc()中的两个地方,您都应该这样写:

返回new_list +1;

  • free()中类似,但不一定会导致错误,您应该避免对void指针执行算术,将它们转换为可移植代码的unsigned char *

块*pref = (void *)((无符号字符*)ptr-大小(块));

或在正确键入后执行算术:

块*pref = ptr;ptr -= 1;

以下是修改后的版本:

代码语言:javascript
复制
static struct list *head = NULL;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

typedef struct list {
    size_t size_;           // block size, including header
    int free_;              // free indicator, true or false
    struct list *next_;
    struct list *previouse_;
} block;

void blockAdd(block *href, size_t size) {
    href->free_ = FALSE;
    href->size_ = size + sizeof(block);
    href->next_ = NULL;
    href->previouse_ = NULL;

    if (!head || head > href) {
        if (head) {
            head->previouse_ = href;
        }
        href->next_ = head;
        head = href;
    } else {
        block *current = head;
        while (current->next_ && current->next_ < href) {
            current = current->next_;
        }
        href->next_ = current->next_;
        if (href->next_) {
            href->next_->previouse_ = href;
        }
        href->previouse_ = current;
        current->next_ = href;
    }
}

void *findExactSizeMatch(size_t size) {
    block *href = head;
    size_t t = size + sizeof(block);

    while (href) {
        if (href->free_ && href->size_ == t) {
            href->free_ = FALSE;
            return href;
        }
        href = href->next_;
    }
    return NULL;
}

void *findLargerBlock(size_t size) {
    block *href = head;
    size_t t = size + sizeof(block);

    while (href) {
        if (href->free_ && href->size_ > t) {
            return split(href, size);
        }
        href = href->next_;
    }
    return NULL;
}

void *allocateMemory(size_t size) {
    /* should add size of `block` */
    block *new_block = sbrk(BLOCK_SIZE(size));

    if (new_block == SBRK_FAILED) {
        exit(1);
    }
    /* should split new_block if BLOCK_SIZE(size) > size */
    blockAdd(new_block, size);

    return new_block;
}

bool checkAllFree() {
    block *href = head;

    while (href) {
        if (!href->free_) {
            return FALSE;
        }
        href = href->next_;
    }
    return TRUE;
}

void freeList(block *ptr) {
    if (checkAllFree()) {
        if (brk(head) == BRK_FAILED) {
            exit(1);
        }
        head = NULL;
    }
}

void merge(void) {
    block *href = head;

    while (href && href->next_) {
        if (href->free_ && href->next_->free_) {
            href->size_ += href->next_->size_;
            href->next_ = href->next_->next_;
            href->next_->previouse_ = href;
        }
        href = href->next_;
    }
}

void shrinkHeap(void) {
    block *href = head;

    if (href) {
        while (href->next_) {
            href = href->next_;
        }
        if (href->free_) {
            if (href->previouse_ != NULL) {
                href->previouse_->next_ = NULL;
            }
            if (brk(href) == BRK_FAILED) {
                exit(1);
            }
        }
    }
}

void *malloc(size_t size) {
    if (!size) {
        return NULL;
    }
    pthread_mutex_lock(&mutex);

    block *new_list = findExactSizeMatch(size);
    if (new_list == NULL) {
        new_list = findLargerSize(size);
    }
    if (new_list == NULL) {
        new_list = allocateMemory(size);
    }
    pthread_mutex_unlock(&mutex);
    if (new_list)
        return new_list += 1;
    else
        return NULL;
}

void free(void *ptr) {
    if (!ptr || !head) {
        return;
    }
    pthread_mutex_lock(&mutex);

    block *pref = ptr;
    pref -= 1;
    pref->free_ = TRUE;

    freeList(pref);
    merge();
    shrinkHeap();

    pthread_mutex_unlock(&mutex);
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61512777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档