2017-01-30 12 views
2

私は現在、メモリアロケータを開発していますが、実装のLD_PRELOADを実行すると、ほぼすべてのコマンドでsegfaultの下にこのコードがあります。ここでメモリアロケータの実装segfault

#include <pthread.h> 
#include "malloc.h" 

t_mem_map  g_map; 
int   g_empty_map = TRUE; 

static t_ctrl  *get_free_block(size_t size) 
{ 
    t_ctrl  *tmp; 

    tmp = g_map.head; 
    while (tmp != NULL) 
    { 
     if (tmp->is_free == TRUE && tmp->size < size) 
    { 
     tmp->is_free = FALSE; 
     return (tmp); 
    } 
     tmp = tmp->next; 
    } 
    return (NULL); 
} 

static void  *init_map(size_t size) 
{ 
    t_ctrl  *tmp; 

    g_map.map_size = DEFAULT_MAP_SIZE; 
    while (g_map.map_size < size + sizeof(t_ctrl)) 
    g_map.map_size += DEFAULT_MAP_SIZE; 
    if ((g_map.head = (t_ctrl *)sbrk(g_map.map_size)) == (void *)-1) 
    return (NULL); 
    tmp = g_map.head; 
    tmp->next = NULL; 
    tmp->prev = NULL; 
    tmp->size = size; 
    tmp->is_free = FALSE; 
    g_map.free_space = g_map.map_size - size - sizeof(t_ctrl); 
    g_empty_map = FALSE; 
    unlock_thread(); 
    return ((void *)((char *)tmp + sizeof(t_ctrl))); 
} 

static void  *add_block(size_t size) 
{ 
    t_ctrl  *tmp; 
    t_ctrl  *new; 

    tmp = get_free_block(size); 
    if (tmp != NULL) 
    return ((void *)((char *)tmp + sizeof(t_ctrl))); 
    tmp = g_map.head; 
    while (tmp->next != NULL) 
    tmp = tmp->next; 
    new = (t_ctrl *)((char *)tmp + sizeof(t_ctrl) + tmp->size); 
    new->prev = tmp; 
    new->next = NULL; 
    tmp->next = new; 
    new->size = size; 
    new->is_free = FALSE; 
    g_map.free_space -= (new->size + sizeof(t_ctrl)); 
    unlock_thread(); 
    return ((void *)((char *)new + sizeof(t_ctrl))); 
} 

static void  *resize_map(size_t size) 
{ 
    size_t  size_shift; 

    size_shift = 0; 
    while (g_map.free_space < size + sizeof(t_ctrl)) 
    { 
     g_map.map_size += DEFAULT_MAP_SIZE; 
     g_map.free_space += DEFAULT_MAP_SIZE; 
     size_shift += DEFAULT_MAP_SIZE; 
    } 
    if (sbrk(size_shift) == (void *)-1) 
    return (NULL); 
    return (add_block(size)); 
} 

void   *malloc(size_t size) 
{ 
    size_t  a_size; 

    lock_thread(); 
    a_size = ALIGN(size); 
    if (g_empty_map == TRUE) 
    return (init_map(a_size)); 
    else 
    { 
     if ((a_size + sizeof(t_ctrl)) <= g_map.free_space) 
     return (add_block(a_size)); 
     else 
    return (resize_map(a_size)); 
    } 
    return (NULL); 
} 

はmalloc.hを次のとおりです。いくつかの研究では

# include <stdio.h> 
# include <stddef.h> 
# include <unistd.h> 

# define TRUE 0 
# define FALSE 1 

# define SUCCESS 0 
# define FAILURE 1 


# ifndef __X86_64__ 
# define ALIGNMENT (16) 
# else 
# define ALIGNMENT (8) 
# endif 

# define ALIGN(size) (((size) + (ALIGNMENT - 1)) &~ (ALIGNMENT - 1)) 
# define DEFAULT_MAP_SIZE (ALIGN(sysconf(_SC_PAGESIZE))) 

typedef struct  s_ctrl 
{ 
    size_t  is_free; 
    size_t  size; 
    struct s_ctrl  *next; 
    struct s_ctrl  *prev; 
}   t_ctrl; 

typedef struct  s_mem_map 
{ 
    size_t  map_size; 
    size_t  free_space; 
    // int   free_blocks; 
    //int   nb_blocks; 
    t_ctrl  *head; 
}   t_mem_map; 

私はセグメンテーション違反の可能性が高いwhileループget_free_blockで()関数から来ているが、私は理由を理解することができないことが判明しました。

static t_ctrl  *get_free_block(size_t size) 
{ 
    t_ctrl  *tmp; 

    tmp = g_map.head; 
    while (tmp != NULL) 
    { 
     if (tmp->is_free == TRUE && tmp->size < size) 
     { 
      tmp->is_free = FALSE; 
      return (tmp); 
     } 
     tmp = tmp->next; 
    } 
    return (NULL); 
} 
+3

まあ、デバッガを使いましたか? SOはそれを置き換えるものではありません。 – OldProgrammer

+0

これは、エラーが発生したアセンブラオペコードであると仮定していますか?腕章か別のもの?また、悪いアクセスが発生したライン上でデバッガが停止することを期待しています。そうではありませんか? –

+0

コードは "ほぼすべてのコマンド"でsegfaultsを実行してから、いくつかの機能を提供し、どのセグメンテーションが一貫しているかを教えてくれません。 [最小完全な例](http://stackoverflow.com/help/mcve)を構築しようとすると、それはすべてを助けるでしょう。 – Beta

答えて

4

は、これが唯一の問題ですが、あなたはおそらく代わりにtmp->size >= size確認する必要がある場合、tmp->size < sizeをチェックしていることを確認することはできません。

+0

ああ私の神私は何度も自分のコードをチェックして、この間違いがあなたにありがとうとは思わなかった。 – Epoch

+1

@エポック:ええ、私はその気持ちを知っています。あなたは[Rubber Duck Debugging](https://en.m.wikipedia.org/wiki/Rubber_duck_debugging)に精通していますか?それはときどき役立ちます。 – MikeMB

+0

いいえ、私はこの方法を知らなかった、アドバイスのおかげで。 – Epoch