Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!lll-winken!ames!sgi!donl@glass.esd.sgi.com From: donl@glass.esd.sgi.com (donl mathis) Newsgroups: comp.sys.sgi Subject: Re: Pointer validation code Message-ID: <84166@sgi.sgi.com> Date: 6 Feb 91 00:57:40 GMT References: <9102041731.aa11984@WOLF.BRL.MIL> Sender: guest@sgi.sgi.com Organization: Silicon Graphics, Inc., Mountain View, CA Lines: 72 In article <9102041731.aa11984@WOLF.BRL.MIL>, mike@BRL.MIL (Mike Muuss) writes: > I handle memory corruption and pointer mis-handling in a rather > different manner. I have "wrapper" subroutines called > rt_malloc(), rt_free(), rt_calloc() that take an extra string > argument which indicates the "purpose" of this allocation/free. > > Depending on the setting of some global variables, you can > independently enable memory activity logging, and memory > checking. The checking includes adding a "barrier" word at the > end of the allocation, to ensure that the application is not > running off the end. It also maintains a full table of what memory > is being used. This table can be printed at any time, by calling > a subroutine (either from the application, or via a "dbx -P"). > > One final note is that most of our application's data structures have > been designed with "magic numbers" as their first word, so that > subroutines can validate that they have been given pointers to the > correct kind of object. > > These two techniques have been very powerful, and have virtually eliminated > the programming difficulties associated with using very complex > dynamic memory allocation in C. I have a similar package that accomplish much the same thing, but in a somewhat more formal environment. My model for memory use was that a program will enter a logical scope where it will be building a new structure of some kind, allocate many bits and pieces within the structure, and then throw the whole thing away at once. Any number of such scopes may coexist. I abandoned the notion of explicitly freeing individual values, and at least in my applications, have not missed it. A scope is created by opening a "memory group", which has a name and perhaps some tuning parameters. A pointer to struct is returned to the caller, and all allocation requests are made against that handled. Relatively large blocks of memory are added to the group as necessary. Each block has a header that contains a pointer to the current free space within the block. Individual allocation requests are generally satisfied by simply keeping an eye on the free count, and bumping the pointer into the block. "Freeing" the group consists of resetting the block pointers, also quite fast. A group can be destroyed and its blocks returned to the pool. Verification gets easier once you have a structure describing the list of blocks, and block headers that describe the memory that is part of the group. It is a simple matter to verify that a pointer to an object of a known size is completely within a block in the group, and that a group appears to be self-consistent. (One of the routines in my test suite repeatedly fires random bytes into memory and calls the verification routines; it usually, though not always, notices a problem before the program dumps core.) On top of these basic mechanisms, there is a user interface layer designed to make memory easy to get and use. Macros provided typed allocation of the appropriate size, and there is an extension to the basic mechanism for variable-sized arrays that grow as necessary when a reference goes out of the current bounds. Macros also providing scaling by N to allocate arrays without a fuss. I do not know how well this mechanism would fit into C++, nor do i know how much of a pain it would be to adapt it to multiprocessing. The package as it sits is about 1300 lines of C. My last tests indicated a significant performance increase over malloc/free, although they were done some time ago, and i don't know what changes have occured since then. -- - donl mathis at Silicon Graphics Computer Systems, Mountain View, CA donl@sgi.com There is One.