Merge pull request #1782 from benpicco/fix_malloc
check if the requested memory is really available in _sbrk_r
This commit is contained in:
commit
cedc588d77
@ -130,8 +130,10 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
|
|
||||||
.flashcca :
|
.flashcca :
|
||||||
{
|
{
|
||||||
|
|||||||
@ -39,18 +39,12 @@
|
|||||||
#ifdef MODULE_UART0
|
#ifdef MODULE_UART0
|
||||||
#include "board_uart0.h"
|
#include "board_uart0.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CPU_MODEL_CC2538NF11
|
|
||||||
#define SRAM_LENGTH (16 * 1024) /**< The CC2538NF11 has 16 Kb of RAM */
|
|
||||||
#else
|
|
||||||
#define SRAM_LENGTH (32 * 1024) /**< All other existing models of the CC2538 have 32 Kb of RAM */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* manage the heap
|
* manage the heap
|
||||||
*/
|
*/
|
||||||
extern uint32_t _end; /* address of last used memory cell */
|
extern char _sheap; /* start of the heap */
|
||||||
caddr_t heap_top = (caddr_t) &_end + 4;
|
extern char _eheap; /* end of the heap */
|
||||||
|
caddr_t heap_top = (caddr_t)&_sheap + 4;
|
||||||
|
|
||||||
#ifndef MODULE_UART0
|
#ifndef MODULE_UART0
|
||||||
/**
|
/**
|
||||||
@ -120,25 +114,26 @@ void _exit(int n)
|
|||||||
* @brief Allocate memory from the heap.
|
* @brief Allocate memory from the heap.
|
||||||
*
|
*
|
||||||
* The current heap implementation is very rudimentary, it is only able to allocate
|
* The current heap implementation is very rudimentary, it is only able to allocate
|
||||||
* memory. It does not have any means to free memory again.
|
* memory. But it does not
|
||||||
|
* - have any means to free memory again
|
||||||
*
|
*
|
||||||
* @return a pointer to the successfully allocated memory
|
* @return [description]
|
||||||
* @return -1 on error, and errno is set to ENOMEM
|
|
||||||
*/
|
*/
|
||||||
caddr_t _sbrk_r(struct _reent *r, size_t incr)
|
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
unsigned int state = disableIRQ();
|
unsigned int state = disableIRQ();
|
||||||
if ((uintptr_t)heap_top + incr > SRAM_BASE + SRAM_LENGTH) {
|
caddr_t res = heap_top;
|
||||||
restoreIRQ(state);
|
|
||||||
|
if (((incr > 0) && ((heap_top + incr > &_eheap) || (heap_top + incr < res))) ||
|
||||||
|
((incr < 0) && ((heap_top + incr < &_sheap) || (heap_top + incr > res)))) {
|
||||||
r->_errno = ENOMEM;
|
r->_errno = ENOMEM;
|
||||||
return (caddr_t)-1;
|
res = (void *) -1;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
caddr_t res = heap_top;
|
|
||||||
heap_top += incr;
|
heap_top += incr;
|
||||||
restoreIRQ(state);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restoreIRQ(state);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -138,6 +138,8 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,8 +41,9 @@
|
|||||||
/**
|
/**
|
||||||
* manage the heap
|
* manage the heap
|
||||||
*/
|
*/
|
||||||
extern uint32_t _end; /* address of last used memory cell */
|
extern char _sheap; /* start of the heap */
|
||||||
caddr_t heap_top = (caddr_t)&_end + 4;
|
extern char _eheap; /* end of the heap */
|
||||||
|
caddr_t heap_top = (caddr_t)&_sheap + 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief use mutex for waiting on incoming UART chars
|
* @brief use mutex for waiting on incoming UART chars
|
||||||
@ -111,18 +112,24 @@ void _exit(int n)
|
|||||||
*
|
*
|
||||||
* The current heap implementation is very rudimentary, it is only able to allocate
|
* The current heap implementation is very rudimentary, it is only able to allocate
|
||||||
* memory. But it does not
|
* memory. But it does not
|
||||||
* - check if the returned address is valid (no check if the memory very exists)
|
|
||||||
* - have any means to free memory again
|
* - have any means to free memory again
|
||||||
*
|
*
|
||||||
* TODO: check if the requested memory is really available
|
|
||||||
*
|
|
||||||
* @return [description]
|
* @return [description]
|
||||||
*/
|
*/
|
||||||
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
unsigned int state = disableIRQ();
|
unsigned int state = disableIRQ();
|
||||||
caddr_t res = heap_top;
|
caddr_t res = heap_top;
|
||||||
heap_top += incr;
|
|
||||||
|
if (((incr > 0) && ((heap_top + incr > &_eheap) || (heap_top + incr < res))) ||
|
||||||
|
((incr < 0) && ((heap_top + incr < &_sheap) || (heap_top + incr > res)))) {
|
||||||
|
r->_errno = ENOMEM;
|
||||||
|
res = (void *) -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
heap_top += incr;
|
||||||
|
}
|
||||||
|
|
||||||
restoreIRQ(state);
|
restoreIRQ(state);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,6 +139,8 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
}
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
|
}
|
||||||
|
|||||||
@ -37,10 +37,9 @@
|
|||||||
/**
|
/**
|
||||||
* manage the heap
|
* manage the heap
|
||||||
*/
|
*/
|
||||||
extern uint32_t _end; /* address of last used memory cell */
|
extern char _sheap; /* start of the heap */
|
||||||
caddr_t heap_top = (caddr_t)&_end + 4;
|
extern char _eheap; /* end of the heap */
|
||||||
|
caddr_t heap_top = (caddr_t)&_sheap + 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize NewLib, called by __libc_init_array() from the startup script
|
* @brief Initialize NewLib, called by __libc_init_array() from the startup script
|
||||||
*/
|
*/
|
||||||
@ -77,18 +76,24 @@ void _exit(int n)
|
|||||||
*
|
*
|
||||||
* The current heap implementation is very rudimentary, it is only able to allocate
|
* The current heap implementation is very rudimentary, it is only able to allocate
|
||||||
* memory. But it does not
|
* memory. But it does not
|
||||||
* - check if the returned address is valid (no check if the memory very exists)
|
|
||||||
* - have any means to free memory again
|
* - have any means to free memory again
|
||||||
*
|
*
|
||||||
* TODO: check if the requested memory is really available
|
|
||||||
*
|
|
||||||
* @return [description]
|
* @return [description]
|
||||||
*/
|
*/
|
||||||
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
unsigned int state = disableIRQ();
|
unsigned int state = disableIRQ();
|
||||||
caddr_t res = heap_top;
|
caddr_t res = heap_top;
|
||||||
heap_top += incr;
|
|
||||||
|
if (((incr > 0) && ((heap_top + incr > &_eheap) || (heap_top + incr < res))) ||
|
||||||
|
((incr < 0) && ((heap_top + incr < &_sheap) || (heap_top + incr > res)))) {
|
||||||
|
r->_errno = ENOMEM;
|
||||||
|
res = (void *) -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
heap_top += incr;
|
||||||
|
}
|
||||||
|
|
||||||
restoreIRQ(state);
|
restoreIRQ(state);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,6 +137,8 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,8 +43,9 @@
|
|||||||
/**
|
/**
|
||||||
* manage the heap
|
* manage the heap
|
||||||
*/
|
*/
|
||||||
extern uint32_t _end; /* address of last used memory cell */
|
extern char _sheap; /* start of the heap */
|
||||||
caddr_t heap_top = (caddr_t)&_end + 4;
|
extern char _eheap; /* end of the heap */
|
||||||
|
caddr_t heap_top = (caddr_t)&_sheap + 4;
|
||||||
|
|
||||||
#ifndef MODULE_UART0
|
#ifndef MODULE_UART0
|
||||||
/**
|
/**
|
||||||
@ -114,18 +115,24 @@ void _exit(int n)
|
|||||||
*
|
*
|
||||||
* The current heap implementation is very rudimentary, it is only able to allocate
|
* The current heap implementation is very rudimentary, it is only able to allocate
|
||||||
* memory. But it does not
|
* memory. But it does not
|
||||||
* - check if the returned address is valid (no check if the memory very exists)
|
|
||||||
* - have any means to free memory again
|
* - have any means to free memory again
|
||||||
*
|
*
|
||||||
* TODO: check if the requested memory is really available
|
|
||||||
*
|
|
||||||
* @return [description]
|
* @return [description]
|
||||||
*/
|
*/
|
||||||
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
unsigned int state = disableIRQ();
|
unsigned int state = disableIRQ();
|
||||||
caddr_t res = heap_top;
|
caddr_t res = heap_top;
|
||||||
heap_top += incr;
|
|
||||||
|
if (((incr > 0) && ((heap_top + incr > &_eheap) || (heap_top + incr < res))) ||
|
||||||
|
((incr < 0) && ((heap_top + incr < &_sheap) || (heap_top + incr > res)))) {
|
||||||
|
r->_errno = ENOMEM;
|
||||||
|
res = (void *) -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
heap_top += incr;
|
||||||
|
}
|
||||||
|
|
||||||
restoreIRQ(state);
|
restoreIRQ(state);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,6 +137,8 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,6 +137,8 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,8 +43,9 @@
|
|||||||
/**
|
/**
|
||||||
* manage the heap
|
* manage the heap
|
||||||
*/
|
*/
|
||||||
extern uint32_t _end; /* address of last used memory cell */
|
extern char _sheap; /* start of the heap */
|
||||||
caddr_t heap_top = (caddr_t)&_end + 4;
|
extern char _eheap; /* end of the heap */
|
||||||
|
caddr_t heap_top = (caddr_t)&_sheap + 4;
|
||||||
|
|
||||||
#ifndef MODULE_UART0
|
#ifndef MODULE_UART0
|
||||||
/**
|
/**
|
||||||
@ -114,18 +115,24 @@ void _exit(int n)
|
|||||||
*
|
*
|
||||||
* The current heap implementation is very rudimentary, it is only able to allocate
|
* The current heap implementation is very rudimentary, it is only able to allocate
|
||||||
* memory. But it does not
|
* memory. But it does not
|
||||||
* - check if the returned address is valid (no check if the memory very exists)
|
|
||||||
* - have any means to free memory again
|
* - have any means to free memory again
|
||||||
*
|
*
|
||||||
* TODO: check if the requested memory is really available
|
|
||||||
*
|
|
||||||
* @return [description]
|
* @return [description]
|
||||||
*/
|
*/
|
||||||
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
unsigned int state = disableIRQ();
|
unsigned int state = disableIRQ();
|
||||||
caddr_t res = heap_top;
|
caddr_t res = heap_top;
|
||||||
heap_top += incr;
|
|
||||||
|
if (((incr > 0) && ((heap_top + incr > &_eheap) || (heap_top + incr < res))) ||
|
||||||
|
((incr < 0) && ((heap_top + incr < &_sheap) || (heap_top + incr > res)))) {
|
||||||
|
r->_errno = ENOMEM;
|
||||||
|
res = (void *) -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
heap_top += incr;
|
||||||
|
}
|
||||||
|
|
||||||
restoreIRQ(state);
|
restoreIRQ(state);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,6 +138,8 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,8 +44,9 @@
|
|||||||
/**
|
/**
|
||||||
* @brief manage the heap
|
* @brief manage the heap
|
||||||
*/
|
*/
|
||||||
extern uint32_t _end; /* address of last used memory cell */
|
extern char _sheap; /* start of the heap */
|
||||||
caddr_t heap_top = (caddr_t)&_end + 4;
|
extern char _eheap; /* end of the heap */
|
||||||
|
caddr_t heap_top = (caddr_t)&_sheap + 4;
|
||||||
|
|
||||||
#ifndef MODULE_UART0
|
#ifndef MODULE_UART0
|
||||||
/**
|
/**
|
||||||
@ -114,18 +115,24 @@ void _exit(int n)
|
|||||||
*
|
*
|
||||||
* The current heap implementation is very rudimentary, it is only able to allocate
|
* The current heap implementation is very rudimentary, it is only able to allocate
|
||||||
* memory. But it does not
|
* memory. But it does not
|
||||||
* - check if the returned address is valid (no check if the memory very exists)
|
|
||||||
* - have any means to free memory again
|
* - have any means to free memory again
|
||||||
*
|
*
|
||||||
* TODO: check if the requested memory is really available
|
|
||||||
*
|
|
||||||
* @return [description]
|
* @return [description]
|
||||||
*/
|
*/
|
||||||
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
unsigned int state = disableIRQ();
|
unsigned int state = disableIRQ();
|
||||||
caddr_t res = heap_top;
|
caddr_t res = heap_top;
|
||||||
heap_top += incr;
|
|
||||||
|
if (((incr > 0) && ((heap_top + incr > &_eheap) || (heap_top + incr < res))) ||
|
||||||
|
((incr < 0) && ((heap_top + incr < &_sheap) || (heap_top + incr > res)))) {
|
||||||
|
r->_errno = ENOMEM;
|
||||||
|
res = (void *) -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
heap_top += incr;
|
||||||
|
}
|
||||||
|
|
||||||
restoreIRQ(state);
|
restoreIRQ(state);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,6 +139,8 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,6 +139,8 @@ SECTIONS
|
|||||||
_estack = .;
|
_estack = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
/* heap section */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_end = . ;
|
_sheap = . ;
|
||||||
|
_eheap = ORIGIN(ram) + LENGTH(ram);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,8 +43,9 @@
|
|||||||
/**
|
/**
|
||||||
* manage the heap
|
* manage the heap
|
||||||
*/
|
*/
|
||||||
extern uint32_t _end; /* address of last used memory cell */
|
extern char _sheap; /* start of the heap */
|
||||||
caddr_t heap_top = (caddr_t)&_end + 4;
|
extern char _eheap; /* end of the heap */
|
||||||
|
caddr_t heap_top = (caddr_t)&_sheap + 4;
|
||||||
|
|
||||||
#ifndef MODULE_UART0
|
#ifndef MODULE_UART0
|
||||||
/**
|
/**
|
||||||
@ -114,18 +115,24 @@ void _exit(int n)
|
|||||||
*
|
*
|
||||||
* The current heap implementation is very rudimentary, it is only able to allocate
|
* The current heap implementation is very rudimentary, it is only able to allocate
|
||||||
* memory. But it does not
|
* memory. But it does not
|
||||||
* - check if the returned address is valid (no check if the memory very exists)
|
|
||||||
* - have any means to free memory again
|
* - have any means to free memory again
|
||||||
*
|
*
|
||||||
* TODO: check if the requested memory is really available
|
|
||||||
*
|
|
||||||
* @return [description]
|
* @return [description]
|
||||||
*/
|
*/
|
||||||
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
caddr_t _sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
unsigned int state = disableIRQ();
|
unsigned int state = disableIRQ();
|
||||||
caddr_t res = heap_top;
|
caddr_t res = heap_top;
|
||||||
heap_top += incr;
|
|
||||||
|
if (((incr > 0) && ((heap_top + incr > &_eheap) || (heap_top + incr < res))) ||
|
||||||
|
((incr < 0) && ((heap_top + incr < &_sheap) || (heap_top + incr > res)))) {
|
||||||
|
r->_errno = ENOMEM;
|
||||||
|
res = (void *) -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
heap_top += incr;
|
||||||
|
}
|
||||||
|
|
||||||
restoreIRQ(state);
|
restoreIRQ(state);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
18
tests/malloc/Makefile
Normal file
18
tests/malloc/Makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# name of your application
|
||||||
|
APPLICATION = test_malloc
|
||||||
|
|
||||||
|
# If no BOARD is found in the environment, use this default:
|
||||||
|
BOARD ?= native
|
||||||
|
|
||||||
|
# This has to be the absolute path to the RIOT base directory:
|
||||||
|
RIOTBASE ?= $(CURDIR)/../..
|
||||||
|
|
||||||
|
# Comment this out to disable code in RIOT that does safety checking
|
||||||
|
# which is not needed in a production environment but helps in the
|
||||||
|
# development process:
|
||||||
|
CFLAGS += -DDEVELHELP
|
||||||
|
|
||||||
|
# Change this to 0 show compiler invocation lines by default:
|
||||||
|
QUIET ?= 1
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.include
|
||||||
82
tests/malloc/main.c
Normal file
82
tests/malloc/main.c
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 Benjamin Valentin <benpicco@zedat.fu-berlin.de>
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||||
|
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tests
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Simple malloc/free test
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Benjamin Valentin <benpicco@zedat.fu-berlin.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define CHUNK_SIZE 1024
|
||||||
|
|
||||||
|
struct node {
|
||||||
|
struct node *next;
|
||||||
|
void *ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
int total = 0;
|
||||||
|
|
||||||
|
void fill_memory(struct node *head)
|
||||||
|
{
|
||||||
|
while (head && (head->ptr = malloc(CHUNK_SIZE))) {
|
||||||
|
printf("Allocated %d Bytes at 0x%p, total %d\n", CHUNK_SIZE, head->ptr, total += CHUNK_SIZE);
|
||||||
|
memset(head->ptr, '@', CHUNK_SIZE);
|
||||||
|
head = head->next = malloc(sizeof(struct node));
|
||||||
|
head->ptr = 0;
|
||||||
|
head->next = 0;
|
||||||
|
total += sizeof(struct node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_memory(struct node *head)
|
||||||
|
{
|
||||||
|
struct node *old_head;
|
||||||
|
|
||||||
|
while (head) {
|
||||||
|
if (head->ptr) {
|
||||||
|
printf("Free %d Bytes at 0x%p, total %d\n", CHUNK_SIZE, head->ptr, total -= CHUNK_SIZE);
|
||||||
|
free(head->ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head->next) {
|
||||||
|
old_head = head;
|
||||||
|
head = head->next;
|
||||||
|
free(old_head);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
free(head);
|
||||||
|
head = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
total -= sizeof(struct node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
struct node *head = malloc(sizeof(struct node));
|
||||||
|
total += sizeof(struct node);
|
||||||
|
|
||||||
|
fill_memory(head);
|
||||||
|
free_memory(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user