[osy] Problem s assertem v mallocu

  • From: Lukas Jezek <lukas.jezek@xxxxxxxxx>
  • To: osy@xxxxxxxxxxxxx
  • Date: Fri, 28 Nov 2008 18:54:43 +0100

Zdarec,

jste z tohohle moudri? Resim to uz celkem dlouho a moc si s tim nevim rady. Pridal jsem si informacni vypisy pri kazde alokaci (viz. prilozeny soubor malloc.c).

Vypada to, ze je zkoruptovany druhy blok pameti (4096B stack idle vlakna) coz mi prijde uplne nejdivnejsi, asi nekde neco zapisuju divne do pameti, budu to muset projet, nenapada vas neco?

Lukas
Initializing Kalisto
Address translation ... OK
Heap structure ...
Physical memory initialization
mm/frame.c:118 find_mainmem_end: total memory: 34ffc00 (52MB)
mm/frame.c:122 find_mainmem_end: status..400004
Raw frames available: 13567
Physical memory frames available: 13563
Physical memory... OK
Heap frames available: 100
 OK
Thread management... OK
Scheduler ...malloc 48 B
malloc at 2148548620 (0x8010400c) of 48 B [block 2148548608 (0x80104000) of 68 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 409532 B free yes
blocks OK
malloc 4096 B
malloc at 2148548688 (0x80104050) of 4096 B [block 2148548676 (0x80104044) of 
4116 B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 405416 B free yes
blocks OK
 OK
Timer management... OK
malloc 48 B
malloc at 2148552804 (0x80105064) of 48 B [block 2148552792 (0x80105058) of 68 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 405348 B free yes
blocks OK
malloc 4096 B
malloc at 2148552872 (0x801050a8) of 4096 B [block 2148552860 (0x8010509c) of 
4116 B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 401232 B free yes
blocks OK
Thread initialized
Runnable
example...
Virtual memory management test #0

Tests the basic functionality of address translation. No allocation is done.

malloc 12 B
malloc at 2148556988 (0x801060bc) of 12 B [block 2148556976 (0x801060b0) of 32 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 401200 B free yes
blocks OK
malloc 24 B
malloc at 2148557020 (0x801060dc) of 24 B [block 2148557008 (0x801060d0) of 44 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 401156 B free yes
blocks OK
malloc 12 B
malloc at 2148557064 (0x80106108) of 12 B [block 2148557052 (0x801060fc) of 32 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 401124 B free yes
blocks OK
malloc 24 B
malloc at 2148557096 (0x80106128) of 24 B [block 2148557084 (0x8010611c) of 44 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 44 B free no
 block 2148557128 (0x80106148) of 401080 B free yes
blocks OK
malloc 4128 B
malloc at 2148557140 (0x80106154) of 4128 B [block 2148557128 (0x80106148) of 
4148 B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 44 B free no
 block 2148557128 (0x80106148) of 4148 B free no
 block 2148561276 (0x8010717c) of 396932 B free yes
blocks OK
malloc 12 B
malloc at 2148561288 (0x80107188) of 12 B [block 2148561276 (0x8010717c) of 32 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 44 B free no
 block 2148557128 (0x80106148) of 4148 B free no
 block 2148561276 (0x8010717c) of 32 B free no
 block 2148561308 (0x8010719c) of 396900 B free yes
blocks OK
malloc 24 B
malloc at 2148561320 (0x801071a8) of 24 B [block 2148561308 (0x8010719c) of 44 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 44 B free no
 block 2148557128 (0x80106148) of 4148 B free no
 block 2148561276 (0x8010717c) of 32 B free no
 block 2148561308 (0x8010719c) of 44 B free no
 block 2148561352 (0x801071c8) of 396856 B free yes
blocks OK
malloc 12 B
malloc at 2148561364 (0x801071d4) of 12 B [block 2148561352 (0x801071c8) of 32 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 44 B free no
 block 2148557128 (0x80106148) of 4148 B free no
 block 2148561276 (0x8010717c) of 32 B free no
 block 2148561308 (0x8010719c) of 44 B free no
 block 2148561352 (0x801071c8) of 32 B free no
 block 2148561384 (0x801071e8) of 396824 B free yes
blocks OK
malloc 24 B
malloc at 2148561396 (0x801071f4) of 24 B [block 2148561384 (0x801071e8) of 44 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 44 B free no
 block 2148557128 (0x80106148) of 4148 B free no
 block 2148561276 (0x8010717c) of 32 B free no
 block 2148561308 (0x8010719c) of 44 B free no
 block 2148561352 (0x801071c8) of 32 B free no
 block 2148561384 (0x801071e8) of 44 B free no
 block 2148561428 (0x80107214) of 396780 B free yes
blocks OK
malloc 12 B
malloc at 2148561440 (0x80107220) of 12 B [block 2148561428 (0x80107214) of 32 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 44 B free no
 block 2148557128 (0x80106148) of 4148 B free no
 block 2148561276 (0x8010717c) of 32 B free no
 block 2148561308 (0x8010719c) of 44 B free no
 block 2148561352 (0x801071c8) of 32 B free no
 block 2148561384 (0x801071e8) of 44 B free no
 block 2148561428 (0x80107214) of 32 B free no
 block 2148561460 (0x80107234) of 396748 B free yes
blocks OK
malloc 24 B
malloc at 2148561472 (0x80107240) of 24 B [block 2148561460 (0x80107234) of 44 
B], check structure of blocks ...
 block 2148548608 (0x80104000) of 68 B free no
 block 2148548676 (0x80104044) of 4116 B free no
 block 2148552792 (0x80105058) of 68 B free no
 block 2148552860 (0x8010509c) of 4116 B free no
 block 2148556976 (0x801060b0) of 32 B free no
 block 2148557008 (0x801060d0) of 44 B free no
 block 2148557052 (0x801060fc) of 32 B free no
 block 2148557084 (0x8010611c) of 44 B free no
 block 2148557128 (0x80106148) of 4148 B free no
 block 2148561276 (0x8010717c) of 32 B free no
 block 2148561308 (0x8010719c) of 44 B free no
 block 2148561352 (0x801071c8) of 32 B free no
 block 2148561384 (0x801071e8) of 44 B free no
 block 2148561428 (0x80107214) of 32 B free no
 block 2148561460 (0x80107234) of 44 B free no
 block 2148561504 (0x80107260) of 396704 B free yes
blocks OK
VMA: directory 2147522676 allocated
before allocVMA: start allocation of 409600 B
VMA: find block according to size ... OK
VMA: split found block: 2148561320 (Start 0, Size 524288 pages)
VMA: split block: 0x801071a8 (Start 0, size 524288) to (start 0, size 100)
malloc 24 B
ASSERT found, block: 0x80104044 (2148548676) of size 4116 B
Assertion failed: mm/malloc.c:138 block_check: foot->magic == 
HEAP_BLOCK_FOOT_MAGIC
[msim] q

Cycles: 974057
/**
 * @file malloc.c
 *
 * Kernel memory allocator.
 *
 * The allocator expects the heap to reside in a continuous physical memory 
range.
 * Heap blocks have headers and footers and are kept next to each other so that
 * traversing can be done by adding or subtracting the appropriate size.
 *
 * The allocation policy is first fit, blocks are merged on free.
 *
 * Kalisto
 *
 * Copyright (c) 2001-2008
 *      Distributed Systems Research Group
 *      Department of Software Engineering
 *      Faculty of Mathematics and Physics
 *      Charles University, Czech Republic
 *
 */

#include <include/shared.h>
#include <include/c.h>
#include <include/debug.h>

#include <drivers/printer.h>
#include <mm/malloc.h>
#include <mm/frame.h>

/* Magic used in heap headers. */
#define HEAP_BLOCK_HEAD_MAGIC  0xBEEF0001

/* Magic used in heap footers. */
#define HEAP_BLOCK_FOOT_MAGIC  0xBEEF0002

/* Some maximum heap block size to avoid overflow. */
#define HEAP_BLOCK_SIZE_MAX    0x10000000

#define HEAP_INIT_FRAME_CNT     100

/* Generic memory alignment */
#define ALIGNMENT  4


/** Header of a heap block
 *
 */
typedef struct {
        /* Size of the block including header and footer */
        size_t size;

        /* Indication of a free block */
        bool free;

        /* A magic value to detect overwrite of heap header.
           The value is at the end of the header because
           that is where writing past block start will
           do damage. */
        uint32_t magic;
} heap_block_head_t;

/** Footer of a heap block
 *
 */
typedef struct {
        /* A magic value to detect overwrite of heap footer.
           The value is at the beginning of the footer
           because that is where writing past block
           end will do damage. */
        uint32_t magic;

        /* Size of the block */
        size_t size;
} heap_block_foot_t;


/**< Address of heap start */
static void *heap_start;

/**< Address of heap end */
static void *heap_end;


/** Initialize a heap block
 *
 * Fills in the structures related to a heap block.
 *
 * @param addr Address of the block.
 * @param size Size of the block including the header and the footer.
 * @param free Indication of a free block.
 *
 */
static void block_init (void *addr, size_t size, bool free)
{
        /* Calculate the position of the header and the footer. */
        heap_block_head_t *head = (heap_block_head_t *) addr;
        heap_block_foot_t *foot
                = (heap_block_foot_t *) (addr + size - sizeof 
(heap_block_foot_t));

        /* Fill the header. */
        head->size = size;
        head->free = free;
        head->magic = HEAP_BLOCK_HEAD_MAGIC;

        /* Fill the footer. */
        foot->magic = HEAP_BLOCK_FOOT_MAGIC;
        foot->size = size;
}


/** Check a heap block
 *
 * Verifies that the structures related to a heap block still contain
 * the magic constants. This helps detect heap corruption early on.
 *
 * @param addr Address of the block.
 *
 */
static void block_check (void *addr)
{
        /* Calculate the position of the header. */
        heap_block_head_t *head;
        head = (heap_block_head_t *) addr;

        /* Make sure the header is still intact. */
        assert (head->magic == HEAP_BLOCK_HEAD_MAGIC);

        /* Calculate the position of the footer. */
        heap_block_foot_t *foot;

        foot = (heap_block_foot_t *) (addr + head->size - sizeof 
(heap_block_foot_t));

        /* Make sure the footer is still intact. */
        if (foot->magic != HEAP_BLOCK_FOOT_MAGIC) {
                printk("ASSERT found, block: %p (%u) of size %u B\n", head, 
head, head->size);
        }
                
        assert (foot->magic == HEAP_BLOCK_FOOT_MAGIC);

        /* And one extra check for the fun of it. */
        assert (head->size == foot->size);
}




/** Initialize the heap allocator
 *
 * Finds how much physical memory we have and creates
 * the heap management structures that mark the whole
 * physical memory as a single free block.
 *
 */
void init_memory (void)
{
        frame_init();

        /* initialize the block of memory using frame_alloc */

        int ret = 0;

        /* allocate HEAP_INIT_FRAME_CNT frames for heap */
        ret = frame_alloc(&heap_start, HEAP_INIT_FRAME_CNT, 0);

        if (ret == EINVAL) {
                print("frame_alloc returned EINVAL\nMemory allocation 
failed.\n");
                msim_halt();
        } else if (ret == ENOMEM) {
                print("frame_alloc returned ENOMEM\nMemory allocation 
failed.\n");
                msim_halt();
        }

        heap_end = heap_start + (HEAP_INIT_FRAME_CNT * FRAME_SIZE);

        printk("Heap frames available: %d\n", HEAP_INIT_FRAME_CNT);

        /* Make the entire area one large block. */
        block_init (heap_start, heap_end - heap_start, true);
}


/** Allocate a memory block
 *
 * @param size The size of the block to allocate.
 * @return The address of the block or NULL when not enough memory.
 *
 */
void *malloc (const size_t size)
{
        printk("malloc %u B\n", size);

        /* Checking for maximum size avoids errors due to
           overflow, which would be hard to debug. */
        assert (size <= HEAP_BLOCK_SIZE_MAX);

        /* Disable interrupts while accessing shared structures. */
        ipl_t state = query_and_disable_interrupts ();

        /* We have to allocate a bit more to have room for
           header and footer. The size of the memory block
           also has to be 4 bytes aligned to avoid unaligned
           memory access exception while accessing the
           footer structure. */
        size_t real_size = ALIGN_UP (size, ALIGNMENT)
                + sizeof (heap_block_head_t) + sizeof (heap_block_foot_t);

        void *result = NULL;

        heap_block_head_t *pos = (heap_block_head_t *) heap_start;
        heap_block_head_t *used = NULL;
        while ((result == NULL) && ((void *) pos < heap_end)) {
                /* Make sure the heap is not corrupted. */
                block_check (pos);

                /* Try to find a block that is free and large enough. */
                if ((pos->free) && (pos->size >= real_size)) {
                        /* We have found a suitable block.
                           See if we should split it. */
                        size_t split_limit = real_size
                                + sizeof (heap_block_head_t) + sizeof 
(heap_block_foot_t);

                        if (pos->size > split_limit) {
                                /* Block big enough -> split. */
                                void *next = ((void *) pos) + real_size;
                                block_init (next, pos->size - real_size, true);
                                block_init (pos, real_size, false);
                        } else {
                                /* Block too small -> use as is. */
                                pos->free = false;
                        }

                        /* Either way we have our result. */
                        result = ((void *) pos) + sizeof (heap_block_head_t);
                        used = pos;
                        
                }
                /* Advance to the next block. */
                pos = (heap_block_head_t *) (((void *) pos) + pos->size);
        }

        printk("malloc at %u (%p) of %u B [block %u (%p) of %u B], check 
structure of blocks ...\n", result, result, size, used, used, used->size);

        pos = (heap_block_head_t *) heap_start;

        while ((void *) pos < heap_end) {
                /* Make sure the heap is not corrupted and advance to the next 
block */
                block_check (pos);
                printk(" block %u (%p) of %u B free %s\n", pos, pos, pos->size, 
pos->free ? "yes" : "no");
                pos = (heap_block_head_t *) (((void *) pos) + pos->size);
        }

        print("blocks OK\n");
        conditionally_enable_interrupts (state);

        return result;
}


/** Allocate a memory block
 *
 * Unlike standard malloc, this routine never returns NULL to
 * indicate an out of memory condition. Recovering from an out
 * of memory condition in the kernel is difficult and we never
 * really need it in the example kernel.
 *
 * @param size The size of the block to allocate.
 * @return The address of the block.
 *
 */
void *safe_malloc (const size_t size)
{
        void *result = malloc (size);
        assert (result != NULL);
        return (result);
}


/** Free a memory block
 *
 * @param addr The address of the block.
 */
void free (const void *addr)
{
        /* Calculate the position of the header. */
        heap_block_head_t *head
                = (heap_block_head_t *) (addr - sizeof (heap_block_head_t));

        /* Make sure the block is not corrupted and not free. */
        block_check (head);
        assert (!head->free);

        /* Disable interrupts while accessing shared structures. */
        ipl_t state = query_and_disable_interrupts ();

        /* Mark the block itself as free. */
        head->free = true;

        /* Look at the next block. If it is free, merge the two. */
        heap_block_head_t *next_head
                = (heap_block_head_t *) (((void *) head) + head->size);

        if ((void *) next_head < heap_end) {
                block_check (next_head);
                if (next_head->free)
                        block_init (head, head->size + next_head->size, true);
        }

        /* Look at the previous block. If it is free, merge the two. */
        if ((void *) head > heap_start) {
                heap_block_foot_t *prev_foot
                        = (heap_block_foot_t *) (((void *) head) - sizeof 
(heap_block_foot_t));

                heap_block_head_t *prev_head
                        = (heap_block_head_t *) (((void *) head) - 
prev_foot->size);

                block_check (prev_head);

                if (prev_head->free)
                        block_init (prev_head, prev_head->size + head->size, 
true);
        }

        conditionally_enable_interrupts (state);
}

Other related posts: