malloc

From Wikipedia, the free encyclopedia

Jump to: navigationsearch

In computingmalloc is a subroutine provided in the C programming language's standard libraryfor performing dynamic memory allocation.

Contents

[hide]

[edit] Rationale

The C programming language manages memory either statically or automatically. Static-duration variables are allocated in main (fixed) memory and persist for the lifetime of the program; automatic-duration variables are allocated on the stack and come and go as functions are called and return. However, both these forms of allocation are somewhat limited, as the size of the allocation must be a compile-time constant.[1] If the required size will not be known until run-time— for example, if data of arbitrary size is being read from the user or from a disk file — using fixed-size data objects is inadequate.

The lifetime of allocated memory is also a concern. Neither static- nor automatic-duration memory is adequate for all situations. Stack-allocated data can obviously not be persisted across multiple function calls, while static data persists for the life of the program whether it is needed or not. In many situations the programmer requires greater flexibility in managing the lifetime of allocated memory.

These limitations are avoided by using dynamic memory allocation in which memory is more explicitly but more flexibly managed, typically by allocating it from a heap, an area of memory structured for this purpose. In C, one uses the library function malloc to allocate a block of memory on the heap. The program accesses this block of memory via a pointer which mallocreturns. When the memory is no longer needed, the pointer is passed to free which deallocates the memory so that it can be reused by other parts of the program.

[edit] Dynamic memory allocation in C

The malloc function is the basic function used to allocate memory on the heap in C. Its prototype is

void *malloc(size_t size);

which allocates size bytes of memory. If the allocation succeeds, a pointer to the block of memory is returned.

malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. Note that because malloc returns a void pointer, it needn't be explictly cast to a more specific pointer type: ANSI C defines an implicit coercion between the void pointer type and other pointer types. An explicit cast of malloc's return value is sometimes performed because mallocoriginally returned a char *, but this cast is unnecessary in modern C code.[2][3]

Memory allocated via malloc is persistent: it will continue to exist until the program terminates or the memory is explicitly deallocated by the programmer (that is, the block is said to be "freed"). This is achieved by use of the free function. Its prototype is

void free(void *pointer);

which releases the block of memory pointed to by pointerpointer must have been previously returned by malloc or calloc (or a function which uses one of these, eg strdup), and must only be passed to free once.

[edit] Usage example

The standard method of creating an array of ten integers on the stack is:

int array[10];

To allocate a similar array dynamically, the following code could be used:

/* Allocate space for an array with ten elements of type int. */
int *ptr = malloc(10 * sizeof (int));
if (ptr == NULL) {
   /* Memory could not be allocated, so print an error and exit. */
   fprintf(stderr, "Couldn't allocate memory\n");
   exit(EXIT_FAILURE);
} 
/* Allocation succeeded. */

[edit] Related functions

[edit] calloc

malloc returns a block of memory that is allocated for the programmer to use, but is uninitialized. The memory is usually initialized by hand if necessary -- either via the memset function, or by one or more assignment statements that dereference the pointer. An alternative is to use thecalloc function, which allocates memory and then initializes it. Its prototype is

void *calloc(size_t nelements, size_t bytes);

which allocates a region of memory large enough to hold nelements of size bytes each. The allocated region is initialized to zero.

[edit] realloc

It is often useful to be able to grow or shrink a block of memory. This can be done using mallocand free: a new block of the appropriate size can be allocated, the content can be copied over, and then the old block can be freed. However, this is somewhat awkward; instead, the reallocfunction can be used. Its prototype is

void *realloc(void *ptr, size_t bytes);

realloc returns a pointer to a memory region of the specified size, which contains the same data as the old region pointed to by ptr (truncated to the minimum of the old and new sizes). If reallocis unable to resize the memory region in-place, it allocates new storage, copies the required data, and frees the old pointer. If this allocation fails, realloc returns the null pointer.

[edit] Common errors

Some programmers find that the improper use of malloc and related functions in C can be a frequent source of bugs.

[edit] Allocation failure

malloc is not guaranteed to succeed — if there is no memory available, or if the program has exceeded the amount of memory it is allowed to reference, malloc will return a NULL pointer. Depending on the nature of the underlying environment, this may or may not be a likely occurrence. Many programs do not check for malloc failure. Such a program would attempt to use the NULL pointer returned by malloc as if it pointed to allocated memory, and the program would crash. This has traditionally been considered an incorrect design, although it remains common, as memory allocation failures only occur rarely in most situations, and the program frequently can do nothing better than to exit anyway. Checking for allocation failure is more important when implementing libraries — since the library might be used in low-memory environments, it is usually considered good practice to return memory allocation failures to the program using the library and allow it to choose whether to attempt to handle the error.

[edit] Memory leaks

When a call to malloccalloc or realloc succeeds, the return value of the call should eventually be passed to the free function. This releases the allocated memory, allowing it to be reused to satisfy other memory allocation requests. If this is not done, the allocated memory will not be released until the process exits — in other words, a memory leak will occur. Typically, memory leaks are caused by losing track of pointers, for example not using a temporary pointer for the return value of realloc, which may lead to the original pointer being overwritten with NULL, for example:

void *ptr;
size_t size = BUFSIZ;

ptr = malloc(size);

/* some further execution happens here... */

/* now the buffer size needs to be doubled */
if (size > SIZE_MAX / 2) {
  /* handle overflow error */
  /* ... */
  return (1);
}
size *= 2;
ptr = realloc(ptr, size);
if (ptr == NULL) {
  /* the realloc failed (it returned NULL), but the original address in ptr has been lost
      so the memory cannot be freed and a leak has occurred */
  /* ... */
  return (1);
}
/* ... */

[edit] Use after free

After a pointer has been passed to free, it references a region of memory with undefined content, which may not be available for use. However, the pointer may still be used, for example:

 int *ptr = malloc(sizeof (int));
 free(ptr);
 *ptr = 0; /* Undefined behavior! */

Code like this has undefined behavior — after the memory has been freed, the system may reuse that memory region for storage of unrelated data. Therefore, writing through a pointer to a deallocated region of memory may result in overwriting another piece of data somewhere else in the program. Depending on what data is overwritten, this may result in data corruption or cause the program to crash at a later time. A particularly bad example of this problem is if the same pointer is passed to free twice, known as a double free. To avoid this, some programmers set pointers to NULL after passing them to freefree(NULL) is safe (it does nothing).

[edit] Implementations

The implementation of memory management depends greatly upon operating system and architecture. Some operating systems supply an allocator for malloc, while others supply functions to control certain regions of data.

The same dynamic memory allocator is often used to implement both malloc and operator new inC++. Hence, we will call this the allocator rather than malloc. (However, note that it is never proper C++ to treat malloc and new interchangeably. For example, free cannot be used to release memory that was allocated with new.[4]

[edit] Heap-based

Implementation of the allocator on IA-32 architectures is commonly done using the heap, or data segment. The allocator will usually expand and contract the heap to fulfill allocation requests.

The heap method suffers from a few inherent flaws, stemming entirely from fragmentation. Like any method of memory allocation, the heap will become fragmented; that is, there will be sections of used and unused memory in the allocated space on the heap. A good allocator will attempt to find an unused area of already allocated memory to use before resorting to expanding the heap. However, due to performance it can be impossible to use an allocator in a real time system and amemory pool must be deployed instead.

The major problem with this method is that the heap has only two significant attributes: base, or the beginning of the heap in virtual memory space; and length, or its size. The heap requires enough system memory to fill its entire length, and its base can never change. Thus, any large areas of unused memory are wasted. The heap can get "stuck" in this position if a small used segment exists at the end of the heap, which could waste any magnitude of address space, from a few megabytes to a few hundred.

[edit] The glibc allocator

The GNU C library (glibc) uses both brk and mmap on the Linux operating system. The brk system call will change the size of the heap to be larger or smaller as needed, while the mmap system call will be used when extremely large segments are allocated. The heap method suffers the same flaws as any other, while the mmap method may avert problems with huge buffers trapping a small allocation at the end after their expiration.

The mmap method has its own flaws. It always allocates a segment by mapping pages. Only one set of mapped pages exists for each allocated segment. Mapping a single byte will use an entire page, usually 4096 bytes, on IA-32; however, large pages are 4MiB, 1024 times larger, and so this method could be particularly devastating if userspace uses only large pages. The advantage to the mmap method is that when the segment is freed, the memory is returned to the system immediately.

<< malloc은 라이브러리 함수이다.>>

 <<malloc은 어떤 시스템 콜을 이용하는 함수일까..를 알아보던 중 참고 할 수 있는 글 >>

- brk, mmap 함수는 테스트 결과, malloc 을 후킹하기 위해 두 시스템 콜을 활용하는데는 무리가 있음.

테스트 프로그램에서 malloc()을 하였지만, mmap은 아예 호출 x, brk()는 malloc() 호출시에만 호출되는 것이 아니라 굉장히 다양한 곳에서 호출됨. 심지어는 

int main(){

return 0;

}


라는 프로그램을 실행해도 brk()는 수십번 호출됨. 


즉 malloc을 후킹하기 위해서 brk, mmap을 사용하는것은 무리가 있음.

[edit] OpenBSD's malloc

OpenBSD's implementation of the malloc function makes use of mmap. For requests greater in size than one page, the entire allocation is retrieved using mmap; smaller sizes are assigned from memory pools maintained by malloc within a number of "bucket pages," also allocated with mmap. On a call to free, memory is released and unmapped from the process address space usingmunmap. This system is designed to improve security by taking advantage of the address space layout randomization and gap page features implemented as part of OpenBSD's mmap system call, and to detect use-after-free bugs—as a large memory allocation is completely unmapped after it is freed, further use causes a segmentation fault and termination of the program.

[edit] Hoard's malloc

The Hoard memory allocator is an allocator whose goal is scalable memory allocation performance. Like OpenBSD's allocator, Hoard uses mmap exclusively, but manages memory in chunks of 64K called superblocks. Hoard's heap is logically divided into a single global heap and a number of per-processor heaps. In addition, there is a thread-local cache that can hold a limited number of superblocks. By allocating only from superblocks on the local per-thread or per-processor heap, and moving mostly-empty superblocks to the global heap so they can be reused by other processors, Hoard keeps fragmentation low while achieving near linear scalability with the number of threads.

[edit] Allocation size limits

The largest possible memory block malloc can allocate depends on the host system, particularly the size of physical memory and the operating system implementation. Theoretically, the largest number should be the maximum value that can be held in a size_t type, which is an implementation-dependent unsigned integer representing the size of an area of memory. The maximum value is (size_t) −1, or the constant SIZE_MAX in the C99 standard. The C standards guarantee that a certain minimum (0x7FFF in C90, 0xFFFF in C99) for at least one object can be allocated.

[edit] References

  1. ^ This is not completely true. For example, in C99, one can declare variable-sized arrays. Also, the alloca() function provided by the GNU C library (and similar functions provided by other libraries) provides the ability to allocate variable-sized automatic variables.
  2. ^ [1]
  3. ^ [2]
  4. ^ [3])

[edit] See also

[edit] External links

Retrieved from "http://en.wikipedia.org/wiki/Malloc"

[출처] about malloc (1)|작성자 

블로그 이미지

kuku_dass

,

http://lxr.linux.no


완전 유명한 홈페이지인데.. 제대로 활용한지는 얼마 안된.. ;;

메인 페이지에서 원하는 커널 버전 범위에 해당하는 링크를 클릭 후~

상단의 drop box에서 원하는 커널 버전을 선택하면

리눅스 커널 전체 소스를 볼 수 있습니다.~ 완전 유용하다는거!! +_+


블로그 이미지

kuku_dass

,

읽기전용으로 sys_call_table이 수정되어서, 바로 수정한 후 insmod를 하게 되면

>> 죽었음


이라는 커널의 짧고 강렬한 멘트와 함께.. 모듈은 정상작동을 하지 못한다.

즉 sys_call_table[index] = our_func  이런식으로 수정하기 전에 아래와 같은 함수를 호출해주어야 한다.

static void disable_page_protection(void)

{

unsigned long value;

asm volatile("mov %%cr0, %0" : "=r" (value));

if ( value & 0x00010000) {

value &= ~0x00010000;

asm volatile("mov %0, %%cr0": : "r" (value));

}

}


static void enable_page_protection(void)

{

unsigned long value;

asm volatile("mov %%cr0, %0" : "=r" (value));

if (!(value & 0x00010000)) {

value |= 0x00010000;

asm volatile("mov %0, %%cr0": : "r" (value));

}

}


사용예)


disable_page_protection();

sys_call_table[__NR_open] = our_open;

enable_page_protection();


참고 : http://blog.naver.com/kkn2988?Redirect=Log&logNo=138441227

블로그 이미지

kuku_dass

,

        for( ptr = (unsigned long)_read_lock;

                ptr < (unsigned long)&init_mm ; ptr += sizeof(void *))

        {

                p = (unsigned long *)ptr;

                if ( p[6] == (unsigned long) sys_close)

                {

                        return (void**)p;

                }

        }

기존 sys_call_table 의 위치를 찾기위해 공개심볼을 이용하는 방법중

2.6.32-41 generic 에서 "init_mm" [~~~~~} undefined 라는 경고에 봉착했고..

insmod로 모듈을 로드가 제대로 되지 않았다.. ㅠ

위의 init_mm 대신 init_task.active_mm 을 이용해보자.

        for( ptr = (unsigned long)_read_lock;

                ptr < (unsigned long)&init_task.active_mm ; ptr += sizeof(void *))

        {

                p = (unsigned long *)ptr;

                if ( p[6] == (unsigned long) sys_close)

                {

                        return (void**)p;

                }

        }

블로그 이미지

kuku_dass

,
블로그 이미지

kuku_dass

,

과연 몇 달 몇 해가 지나도 이곳에 글들이 넘쳐나고있을까..?

블로그 이미지

kuku_dass

,