magic_numbers revision 499b34cea04a46823d003d4c0520c8b03e8513cb
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinCopyright (C) 1999-2001 Internet Software Consortium.
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark AndrewsSee COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
75c0816e8295e180f4bc7f10db3d0d880383bc1cMark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein$Id: magic_numbers,v 1.5 2001/01/09 21:47:01 bwelling Exp $
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinMagic Numbers
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinA number of data structures in the ISC and DNS libraries have an unsigned int
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinmagic number as the first field. The purpose of the magic number is
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinprincipally to validate that a pointer a subroutine has gotten really points
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinto the type it claims to be. This helps detect problems caused by resources
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinbeing freed prematurely, that have been corrupted, or that have not been
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinproperly initalized. It can also be handy in debugging.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinMagic numbers should always be the first field. They never require locking
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinto access. As to the actual value to be used, something mnemonic is good:
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein #define TASK_MAGIC 0x5441534BU /* TASK. */
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein #define VALID_TASK(t) ((t) != NULL && \
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein (t)->magic == TASK_MAGIC)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews #define TASK_MANAGER_MAGIC 0x54534B4DU /* TSKM. */
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein #define VALID_MANAGER(m) ((m) != NULL && \
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein (m)->magic ==
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein TASK_MANAGER_MAGIC)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinUnless the memory cost is critical, most objects should have a magic number.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe magic number should be the last field set in a creation routine, so that
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinan object will never be stamped with a magic number unless it is valid.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe magic number should be set to zero immediately before the object is
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinfreed.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinMagic values are generally private to the implementation of the type. I.e.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinthey are defined in the .c file, not the .h file.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinValidation of magic numbers is done by routines that manipulate the type,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinnot by users of the type. Indeed, user validation is usually not possible
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinbecause the magic number is not public.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinMagic number checking may become a build option in a future release. E.g.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein struct foo {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein ISC_MAGIC_DECLARATION
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein /* ... */
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein foo_create() {
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews /* ... */
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews ISC_MAGIC_SET(value);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews foo_destroy() {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein /* ... */
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews ISC_MAGIC_CLEAR(value);
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein #define FOO_MAGIC 0x00010203U
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein #define VALID_FOO(f) ISC_MAGIC_VALIDATE(f, FOO_MAGIC)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein foo_dosomething(foo *f) {
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews REQUIRE(VALID_FOO(f));
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein