id:isshikiさんと、valgrindは素晴らしいけどWindowsでは使えん的な話をしてて。Electric Fenceみたいなものだったらすぐできんじゃないかと思って、超やっつけで書いた↓
enum chunk_state_t { CHUNK_FREE, CHUNK_ALLOCATED, }; struct chunk { enum chunk_state_t state; size_t page_size; size_t mem_size; void *mem_addr; void *page_addr; }; #define PAGE_SIZE 4096 #define CHUNK_NUM 1024 static struct chunk chunks[CHUNK_NUM]; static int initialized; static struct chunk * find_chunk( void *p ) { int i; for ( i=0; i<CHUNK_NUM; i++ ) { if ( chunks[i].state == CHUNK_ALLOCATED && chunks[i].mem_addr == p ) return chunks+i; } return NULL; } static struct chunk * alloc_chunk( void ) { int i; for ( i=0; i<CHUNK_NUM; i++ ) { if ( chunks[i].state == CHUNK_FREE ) return chunks+i; } MessageBox( NULL, "oh! memory wariatesugidayo!", "orz OTL", MB_OK ); *(char*)0 = 0; return NULL; } void * malloc( size_t sz ) { size_t page_aligned_size; char *page_memory; char *mem_addr; DWORD old_prot; struct chunk *chunk; page_aligned_size = (sz+(PAGE_SIZE-1))&~(PAGE_SIZE-1); page_memory = VirtualAlloc( NULL, page_aligned_size+PAGE_SIZE, MEM_RESERVE, PAGE_EXECUTE_READWRITE ); VirtualAlloc( page_memory, page_aligned_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); mem_addr = page_memory + page_aligned_size-sz; chunk = alloc_chunk( ); chunk->state = CHUNK_ALLOCATED; chunk->page_size = page_aligned_size + PAGE_SIZE; chunk->mem_size = sz; chunk->page_addr = page_memory; chunk->mem_addr = mem_addr; return mem_addr; } void * realloc( void *ptr, size_t resize ) { struct chunk *c; void *new_ptr; if ( ptr == NULL ) return malloc( resize ); c = find_chunk( ptr ); if ( c == NULL ) { MessageBox( NULL, "WARNING: hennna realloc", "orz", MB_OK ); return malloc( resize ); } if ( c->mem_size > resize ) return c->mem_addr; new_ptr = malloc( resize ); memcpy( new_ptr, ptr, c->mem_size ); free( ptr ); return new_ptr; } void free( void *ptr ) { int i; for ( i=0; i<CHUNK_NUM; i++ ) { if ( chunks[i].mem_addr == ptr ) { if ( chunks[i].state != CHUNK_ALLOCATED ) { MessageBox( NULL, "WARNING: double free", "orz", MB_OK ); return; } VirtualFree( chunks[i].page_addr, chunks[i].page_size, MEM_RELEASE ); chunks[i].state = CHUNK_FREE; return; } } MessageBox( NULL, "WARNING: free not allocated memory.", "orz", MB_OK ); }
int main() { char *p = malloc( 3 ); p[0] = 'a'; puts("0"); p[1] = 'a'; puts("1"); p[2] = 'a'; puts("2"); p[3] = 'a'; /* ここで */ puts("3"); free( p ); return 0; }
こういうプログラムを書くと、p[3] = 'a'のところで落ちます。これを一緒にリンクして、なんだかんだ。
超簡単にgdbの使い方も書いておきます。
$ gdb xxx.exe # gdbをこれで実行 > run # これでプログラムが開始 recieve SIGSEGV # (とかそんな感じのメッセージ) > bt # backtraceコマンド実行 # バックトレースがだらだらと
これでどうでしょう?