?? tmemcheck.c
字號:
/****************************************************************************** * Memory Checker * * Copyright (C) 2002 Hal Duston * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * ******************************************************************************/#ifdef HAVE_CONFIG_H# include <config.h>#endif#ifdef HAVE_ERRNO_H# include <errno.h>#endif#ifndef HAVE_DECL_ERRNOextern int errno;#endif#include <stdio.h>#ifdef STDC_HEADERS# include <stdlib.h># include <stddef.h>#else# ifdef HAVE_STDLIB_H# include <stdlib.h># endif#endif#ifdef HAVE_SIGNAL_H# include <signal.h>#endif#ifdef HAVE_STRING_H# include <string.h>#else# ifdef HAVE_STRINGS_H# include <strings.h># endif#endif#ifdef HAVE_SETJMP_H# include <setjmp.h>#endif#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_FCNTL_H# include <fcntl.h>#endif#ifdef HAVE_MALLOC_H# include <malloc.h>#endif/* This mess was copied from the autoconf acspecific.m4, *//* which in turn was copied from the GNU getpagesize.h. */#ifndef HAVE_GETPAGESIZE# ifdef _SC_PAGESIZE# define getpagesize() sysconf(_SC_PAGESIZE)# else /* no _SC_PAGESIZE */# ifdef HAVE_SYS_PARAM_H# include <sys/param.h># ifdef EXEC_PAGESIZE# define getpagesize() EXEC_PAGESIZE# else /* no EXEC_PAGESIZE */# ifdef NBPG# define getpagesize() NBPG * CLSIZE# ifndef CLSIZE# define CLSIZE 1# endif /* no CLSIZE */# else /* no NBPG */# ifdef NBPC# define getpagesize() NBPC# else /* no NBPC */# ifdef PAGESIZE# define getpagesize() PAGESIZE# endif /* no PAGESIZE */# endif /* no NBPC */# endif /* no NBPG */# endif /* no EXEC_PAGESIZE */# else /* no HAVE_SYS_PARAM_H */# define getpagesize() 8192 /* punt totally */# endif /* no HAVE_SYS_PARAM_H */# endif /* no _SC_PAGESIZE */#elseextern int getpagesize(void);#endif /* no HAVE_GETPAGESIZE */#include "memcheck.h" #define MEMCHECK_INFO 3#define MEMCHECK_WARN 2#define MEMCHECK_ERROR 1#define MEMCHECK_NONE 0#define check_result_error(string,check) \ check_result(string,check,1)#define check_result_warn(string,check) \ check_result(string,check,77)#define check_result(string,check,result) \ if(printf("Checking %s\t: ", string) < 0) \ { \ tmemcheck_error("printf"); \ } \ if(check) \ { \ if(printf("passed\n") < 0) \ { \ tmemcheck_error("printf"); \ } \ } \ else \ { \ if(printf("failed\n") < 0) \ { \ tmemcheck_error("printf"); \ } \ if(tmemcheck_result == 0) \ { \ tmemcheck_result = result; \ } \ else \ { \ tmemcheck_result = result < tmemcheck_result \ ? result : tmemcheck_result; \ } \ }#define check_result_error_in_log(string, tlevel, text) \ if(tmemcheck_config.level >= tlevel) \ { \ if(tmemcheck_log < 0) \ { \ tmemcheck_log = open("memcheck.log", O_RDONLY); \ } \ if(tmemcheck_log >= 0) \ { \ read(tmemcheck_log, buffer, sizeof(buffer) - 1); \ lseek(tmemcheck_log, 0, SEEK_END); \ check_result_error(string, \ !memcmp(buffer, text, strlen(text) - 1)); \ } \ }struct tmemcheck_config{ int underruns; int level; size_t large; size_t limit;};static struct tmemcheck_config tmemcheck_config;static int tmemcheck_result;int main(int argc, char *argv[]);static void tmemcheck_exit(void);#ifdef HAVE_SIGINFO_Tstatic RETSIGTYPE tmemcheck_handler(int signum, siginfo_t *info, void *context, void *address);#elsestatic RETSIGTYPE tmemcheck_handler(int signum, int code, void *context, void *address);#endifstatic void tmemcheck_error(const char *s);static sig_atomic_t tmemcheck_signalled;static sig_atomic_t tmemcheck_setjmp_active;#ifdef HAVE_SIGJMP_BUFstatic sigjmp_buf tmemcheck_handler_env;#else# ifdef HAVE_JMP_BUFstatic jmp_buf tmemcheck_handler_env;# endif#endifstatic int tmemcheck_log = -1;static int tmemcheck_fail = -1;int main(int argc, char *argv[]){ const char *val; const char *env; static char memcheck[] = "memcheck"; static char *s1; static char *s2; unsigned long line[3]; char buffer[1024]; size_t pagesize; unsigned count; unsigned align; unsigned bit;#ifdef HAVE_SIGACTION# ifdef HAVE_SIGACTION_T sigaction_t act;# else# ifdef HAVE_STRUCT_SIGACTION struct sigaction act;# endif# endif#endif (void)argc; (void)argv; unlink("memcheck.log"); if(atexit(tmemcheck_exit)) { tmemcheck_error("atexit"); } if(setvbuf(stdout, NULL, _IONBF, 0)) { tmemcheck_error("setvbuf"); } pagesize = getpagesize(); if((env = getenv("MEMCHECK"))) { if(strstr(env, "under")) { tmemcheck_config.underruns = 1; } if((val = strstr(env, "level="))) { if(val[6] == 'i') { tmemcheck_config.level = MEMCHECK_INFO; } if(val[6] == 'w') { tmemcheck_config.level = MEMCHECK_WARN; } if(val[6] == 'e') { tmemcheck_config.level = MEMCHECK_ERROR; } } if((val = strstr(env, "large="))) { tmemcheck_config.large = atoi(&val[6]); } if((val = strstr(env, "limit="))) { char *modifier; tmemcheck_config.limit = strtol(&val[6], &modifier, 10); if(modifier[0] == 'k' || modifier[0] == 'K') { tmemcheck_config.limit *= 1024; } if(modifier[0] == 'm' || modifier[0] == 'M') { tmemcheck_config.limit *= 1024 * 1024; } if(modifier[0] == 'g' || modifier[0] == 'G') { tmemcheck_config.limit *= 1024 * 1024 * 1024; } tmemcheck_config.limit /= pagesize; } }/* Basic functionality checking, based on validations in "The Standard C Library" by P J Plauger. */ check_result_error("malloc return value",\ (s1 = malloc(sizeof(memcheck))) != NULL); check_result_error("malloc writable",\ strcpy(s1, memcheck) != NULL) check_result_error("malloc readable",\ !strcmp(s1, memcheck)); check_result_error("calloc return value",\ (s2 = calloc(sizeof(memcheck), 1)) != NULL); check_result_error("calloc initialization",\ s2[0] == 0 && !memcmp(&s2[0], &s2[1], sizeof(memcheck) - 1)); check_result_error("calloc writable",\ strcpy(s2, memcheck) != NULL); check_result_error("calloc readable",\ !strcmp(s2, memcheck)); check_result_error("realloc increase",\ (s1 = realloc(s1, 2 * sizeof(memcheck) - 1)) != NULL); check_result_error("realloc inc writable",\ strcat(s1, memcheck) != NULL); check_result_error("realloc inc readable",\ !strcmp(&s1[sizeof(memcheck) - 1], memcheck)); check_result_error("realloc orig readable",\ !memcmp(s1, memcheck, sizeof(memcheck) - 1)); check_result_error("realloc decrease",\ (s1 = realloc(s1, sizeof(memcheck))) != NULL); check_result_error("realloc dec writeable",\ !(s1[sizeof(memcheck) - 1] = 0)); check_result_error("realloc dec readable",\ !memcmp(s1, memcheck, sizeof(memcheck) - 1)); free(s2); free(s1); /* * The POSIX Standard (IEEE Std 1003.1-200x) defers to the ISO C standard. * The ISO C Standard (ISO 9899:1990) states: * * "If the space requested is zero, the behaviour is implementation-defined; * the value returned shall be either a null pointer or a unique pointer." * * This implementation always returns a unique pointer. */ check_result_error("malloc size zero", (s1 = malloc(0)) != NULL); check_result_error_in_log("malloc size zero log", MEMCHECK_INFO, "Zero size"); check_result_error("malloc zero unique", (s2 = malloc(0)) != s1); check_result_error_in_log("malloc zero unique log", MEMCHECK_INFO, "Zero size"); free(s2); free(s1); check_result_error("calloc size zero", (s1 = calloc(1, 0)) != NULL); check_result_error_in_log("calloc size zero log", MEMCHECK_INFO, "Zero size"); check_result_error("calloc zero items", (s2 = calloc(0, 1)) != NULL); check_result_error("calloc zero unique", s2 != s1); free(s2); check_result_error("realloc size zero", (s1 = realloc(s1, 0)) != NULL); check_result_error_in_log("realloc size zero log", MEMCHECK_INFO, "Zero size"); check_result_error("realloc NULL pointer", (s2 = realloc(NULL, 0)) != NULL); check_result_error_in_log("realloc NULL ptr log", MEMCHECK_INFO, "NULL pointer"); free(s2); free(NULL); check_result_error_in_log("free NULL ptr log", MEMCHECK_INFO, "NULL pointer");#ifdef HAVE_SIGACTION# ifdef HAVE_SIGINFO_T act.sa_sigaction = (RETSIGTYPE (*)(int signum, /* Cast away 4th arg */ siginfo_t *info, /* (address) that SunOS */ void *context))tmemcheck_handler; /* _may_ have */ act.sa_flags = SA_SIGINFO;# else act.sa_handler = (RETSIGTYPE (*)(int))tmemcheck_handler; act.sa_flags = 0;# endif if(!sigemptyset(&act.sa_mask)) { if(sigaction(SIGSEGV, &act, NULL)) { tmemcheck_error("sigaction"); } if(sigaction(SIGBUS, &act, NULL)) { tmemcheck_error("sigaction"); } } else { tmemcheck_error("sigemptyset"); }#endif if(printf("Checking %s %d\t: ", "realloc loop of", 1024) < 0)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -