Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!matrix!venkat From: venkat@matrix.UUCP (D Venkatrangan) Newsgroups: comp.sys.ibm.pc.programmer Subject: Re: NULL pointer error Keywords: Null dos error Message-ID: <157@matrix.UUCP> Date: 16 Jul 90 16:40:07 GMT References: <2008@bnlux0.bnl.gov> <27092@netnews.upenn.edu> Reply-To: venkat@matrix.UUCP (D Venkatrangan) Organization: Matrix Computer Systems Inc. Lines: 95 In article <27092@netnews.upenn.edu> weisen@eniac.seas.upenn.edu.UUCP (Neil Weisenfeld) writes: >In article <2008@bnlux0.bnl.gov> reilly@bnlux0.bnl.gov (kevin reilly) writes: >[NULL ptr stuff deleted] >>I guess the question is: What memory address do I watch when stepping >>through the program? > >If the program is attempting to write to a NULL pointer, you could >try watching address 0x0000:0x0000 as this is where the "NULL" pointer >points. > >Neil If you linked with Microsoft supplied libraries, you probably pulled in their exit() function definition, and the _nullcheck() function that it calls. This function actually takes a guess at whether your program changed something outside of memory using a NULL pointer. The code for _nullcheck is probably in your Microsoft compiler/linker software distribution, in a module chksum.asm. The following lines from that module give some insights into this. Starting from DS:0, for a length of 0x42, each succesive byte is xor'ed into the xor'ed result so far. Then, this value is compared with the value that is to be expected if none of the bytes were changed when your program ran. If they are different, the routine assumes that your code accessed data using a NULL pointer. This assumption can be incorrect for the following reasons: 1) you accessed a byte within the first 66 bytes of your DS and changed it, and also another byte within that same region in such a way that xor'ing the new sequence of bytes still gives the same checksum. 2) you changed a byte and the checksum byte as well, so that the change is undetectable. 3) you used a NULL pointer as a pointer to a structure and accessed a member of the structure that was displaced by more than 66 bytes from the start of that structure. (Fo eg, if struct param { char first[66]; char second; }; and NULL->second = x;). Incidentally, this is why you can't just watch 0x0000:0x0000 as an earlier poster had suggested. 4) you used a different DS and used a NULL pointer. This can happen if you use assembly routines and changed DS somewhere. Despite these limitations, _nullcheck() does catch quite a few of errant NULL pointer usage. /* THIS IS FROM Microsoft's CHKSUM.ASM module */ chkpt db 8 dup(0) ; for null pointer assignment CHKSUM= 11h ; has to be correct or error db 'MS Run-Time Library - Copyright (c) 1988, Microsoft Corp' chkb db CHKSUM ; checksum byte db 0 ; leaves al = 0 chkln= $ - chkpt ; length to checksum cProc _nullcheck,,<> cBegin nogen ; no arguments - so no frame push si xor si,si ; start at DS:0 mov cx,chkln xor ah,ah cld chkloop: ; loop to 1 past end of copyrt. string lodsb xor ah,al ; accumulate xor total in AH loop chkloop xor ah,BIAS ; XOR out the initial BIAS jz setzero call _FF_MSGBANNER ; (1) "\r\n" to stderr ; (2) FORTRAN $DEBUG file/line ; if _Fline is set (not in C) ; (3) "run-time error" banner mov ax,1 ; null pointer assignment message no. push ax call _NMSG_WRITE ; write message out mov ax,1 ; indicate error occurred ; ax = 0 if the checksum is OK setzero: pop si ret cEnd nogen --------------------------------------------------------------------------- D. Venkatrangan Matrix Computer Systems, Inc. 7 1/2 Harris Rd, Nashua, NH 03062 suneast!venkat uunet!matrix!venkat (603) 888-7790 ---------------------------------------------------------------------------