reilly@bnlux0.bnl.gov (kevin reilly) (07/13/90)
After exiting my program DOS writes an error to the screen NULL pointer error R6001 I understand the meaning of the error message but how do I go about debugging the program to find what is causing it. From reading the documentation from MicroSoft (QC2.5) the program will compile and link error free. But when run and then exited that is when the error will appear. The program ran error free up until I linked in the menu.obj file that came with the compiler. I guess the question is: What memory address do I watch when stepping through the program? Thank you in advance! reilly@bnlux0.bnl.gov
weisen@eniac.seas.upenn.edu (Neil Weisenfeld) (07/14/90)
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 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Neil I. Weisenfeld | InterNet: weisen@eniac.seas.upenn.edu Dept. of Computer and Info. Sciences | USPS: I dunno, I'm moving... University of Pennsylvania | PENNmail: Don't even try it... =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
steve@taumet.com (Stephen Clamage) (07/16/90)
weisen@eniac.seas.upenn.edu (Neil Weisenfeld) writes: >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. Sadly, it's not this simple. The NULL pointer error is reported for a range about about 128 bytes starting at data address zero. In a small data model program, this is not 0x0000:0x0000, but addresses DS:0x0000 - DS:0x007F. I don't believe this error can be reliably reported for other-model programs, since there is no place to put the checksummed data for comparison at program exit. -- Steve Clamage, TauMetric Corp, steve@taumet.com
trier@cwlim.CWRU.EDU (Stephen C. Trier) (07/16/90)
Debugging a null pointer error is a little simpler than it may seem. The most likely two locations to watch are DS:0000 and DS:0008. The first is NULL and the second is where a malloc'ed pointer will point if it is mistakenly typecast to a near pointer. With Turbo C, the low memory area checked is filled with the Borland Copyright. It is checksummed as part of the exit code and the error message is printed if the checksum is incorrect. _Any_ write to that area should be considered a bug. Note that another common cause of null pointer errors is code like the following: int a; scanf("%d", a); "a" will be interpreted as a pointer, causing a random write into memory corresponding to whatever is in "a" when scanf is called. If "a" is 0, you will receive a null pointer error. -- Stephen Trier Case Western Reserve University Home: sct%seldon@scl.cwru.edu Information Network Services Work: trier@cwlim.ins.cwru.edu I do _not_ speak for the University.
venkat@matrix.UUCP (D Venkatrangan) (07/16/90)
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,<PUBLIC>,<> 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 ---------------------------------------------------------------------------
geiser@apollo.HP.COM (Wayne Geiser) (07/16/90)
In article <2008@bnlux0.bnl.gov>, reilly@bnlux0.bnl.gov (kevin reilly) writes: |> After exiting my program DOS writes an error to the screen |> NULL pointer error R6001 |> I understand the meaning of the error message but how do I go about |> debugging the program to find what is causing it. |> From reading the documentation from MicroSoft (QC2.5) the program will |> compile and link error free. But when run and then exited that is when |> the error will appear. |> The program ran error free up until I linked in the menu.obj file that |> came with the compiler. |> I guess the question is: What memory address do I watch when stepping |> through the program? |> Thank you in advance! |> reilly@bnlux0.bnl.gov What I have done in my Microsoft C programs to help find such problems is to add the following line at the end of each routine: assert(_nullcheck()); If you don't want the assertion there in released code, put a #ifdef around it. This line will call the Microsoft runtime routine to check the section of memory everyone's been describing here and tell you the file and line number when it does occur. Just pointing a finger at the offending routine is usually enough to elicit an "Oh yea! Boy was that stupid!" (at least for me). Wayne Geiser Apollo Computer, Inc. - A subsidiary of Hewlett Packard geiser@apollo.hp.com "The holy passion of Friendship is of so sweet and steady and loyal and enduring a nature that it will last through a whole lifetime - if not asked to lend money." - Mark Twain.
kdq@demott.COM (Kevin D. Quitt) (07/17/90)
In article <2008@bnlux0.bnl.gov> reilly@bnlux0.bnl.gov (kevin reilly) writes: >After exiting my program DOS writes an error to the screen >NULL pointer error R6001 >I understand the meaning of the error message but how do I go about >debugging the program to find what is causing it. >From reading the documentation from MicroSoft (QC2.5) the program will >compile and link error free. But when run and then exited that is when >the error will appear. >The program ran error free up until I linked in the menu.obj file that >came with the compiler. >I guess the question is: What memory address do I watch when stepping >through the program? Microsoft C reserves the first chunk of your data segment (starting at DS:0) to help protect you against yourself. If you look at a link map, you will see a segment called NULL. The NULL segment contains the Microsoft copyright and some other miscellaneous non-junk. When your program exits, the MS library checks to see if you've corrupted this area (generally by using a null pointer) and reports the R6001 error if you have. If you're using codeview, you can look for uninitialized pointers, or pointers that get clobbered. You can also look at DS:0 to see if you recognize the data there. Good Luck -- _ Kevin D. Quitt demott!kdq kdq@demott.com DeMott Electronics Co. 14707 Keswick St. Van Nuys, CA 91405-1266 VOICE (818) 988-4975 FAX (818) 997-1190 MODEM (818) 997-4496 PEP last 96.37% of all statistics are made up.
apn@Apple.COM (Alex Novickis) (07/17/90)
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 > > try watching DS:0000, thats where the MSC null-pointer-error-checking routine places some test data to check for this condition. Look through your startup source files, microsoft distrubutes these! -- Alex P. Novickis, Real Time systems demi-guru. (W) 408-370-4541 ALINK:alex.n (PAGE) 989-6678 UUCP:{amdahl,claris,pyramid,sun,decwrl,well,ubvax,ames}!apn@apple.com,apn@nonvon "I think... I think it's in my basement. Let me go upstairs and check"-Escher.
weisen@eniac.seas.upenn.edu (Neil Weisenfeld) (07/17/90)
In article <4ba0b259.20b6d@apollo.HP.COM> geiser@apollo.HP.COM (Wayne Geiser) writes: > >What I have done in my Microsoft C programs to help find such problems is to >add the following line at the end of each routine: > >assert(_nullcheck()); > >If you don't want the assertion there in released code, put a #ifdef around it. >This line will call the Microsoft runtime routine to check the section of >memory everyone's been describing here and tell you the file and line number >when it does occur. Why not just use the ifdef that's there? The assert macro expands to a call with #ifdef NDEBUG around it. Defining NDEBUG will keep the assertion from being compiled in. Neil P.S. -- Thanks for the _nullcheck tip. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Neil I. Weisenfeld | InterNet: weisen@eniac.seas.upenn.edu Dept. of Computer and Info. Sciences | USPS: I dunno, I'm moving... University of Pennsylvania | PENNmail: Don't even try it... =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=