From: gershon%irit.cs.utah.edu@cs.utah.edu (Elber Gershon)
Subject: Re: NT October release C++ bugs
Date: 18 Dec 92 15:57:54 MST
Organization: University of Utah CS Dept

In article <1992Dec14.160558.7685@hellgate.utah.edu> gershon%irit.cs.utah.edu@cs.utah.edu (Elber Gershon) writes:
>Below are several bugs in the C++ of the beta october release of window NT.
>I would appreciate if someone can upload this to Compuserve as Microsoft
>requests since I have no such access.
>
>	All small programs below fail on the NT C++ compiler but
>succeed using unix AT&T 2.1/3.0 C++ as well as Sun and SGI C++ compiler.
>All these small examples were extracted from a very large C++ project that
>runs under unix for several years. All compiled in NT using 'cl -c -Tp file.c'.
>
	In continuation of the NT C++ bug list message I posted few days ago,
here are some running time bugs and general programming questions in NT.
Again I had appreciate if it can be forwarded to Compuserve/Microsoft.

* The following small program (compiled with the same flags as simple.c in
  the sample directory in text mode) generates wrong code:

  #include <stdio.h>
  
	void main()
	{
	    double d;
	    int i, j;
	
	    for ( i=0; i<4; i++ ) {
	        for ( j=0; j<4; j++ ) {
	/*
	            if ( i == j )
	                d = 1.0;
	            else
	                d = 0.0;
	*/
	            d = (i == j) ? 1.0 : 0.0;
	
	            fprintf(stderr, "(%d, %d) = %lf\n", i, j, d);
	        }
	    }
	}

  and the output is 

	(0, 0) = 0.000000
	(0, 1) = 0.000000
	(0, 2) = 0.000000
	(0, 3) = 0.000000
	(1, 0) = 0.000000
	(1, 1) = 0.000000
	(1, 2) = 0.000000
	(1, 3) = 0.000000
	(2, 0) = 0.000000
	(2, 1) = 0.000000
	(2, 2) = 0.000000
	(2, 3) = 0.000000
	(3, 0) = 0.000000
	(3, 1) = 0.000000
	(3, 2) = 0.000000
	(3, 3) = 0.000000

  Surprisingly enough, '(i == j) ? 1.0 : 0.0;' is returning only zeros.
  The equivalent 'if - then - else' that is commented out is o.k. Below
  is the relevant Assembly code from the cod file:

	; 10   : /*
	; 11   :            if ( i == j )
	; 12   :                d = 1.0;
	; 13   :            else
	; 14   :                d = 0.0;
	; 15   : */
	; 16   :            d = (i == j) ? 1.0 : 0.0;
	
	  0003b 8b 45 f4        mov     eax, DWORD PTR _i$[ebp]
	  0003e 39 45 f0        cmp     DWORD PTR _j$[ebp], eax
	  00041 0f 85 07 00 00
	        00              jne     $L195
	  00047 d9 e8           fld1
	  00049 e9 0d 00 00 00  jmp     $L194
	$L195:
	  0004e a1 04 00 00 00  mov     eax, DWORD PTR $T197+4
	  00053 89 45 fc        mov     DWORD PTR _d$[ebp+4], eax
	  00056 a1 00 00 00 00  mov     eax, DWORD PTR $T197
	$L194:
	  0005b 89 45 f8        mov     DWORD PTR _d$[ebp], eax

  For i == j only half of the double 8 bytes are actually updated at all...

* Let class obj1type have no virtual function. Let class obj2type have
  a virtual function and let obj2type inherit from obj1type. The following
  code demonstrate such a possible situation.
	
	#include <stdio.h>
	
	class obj1type
	{
	    unsigned		m_size;
	
	  public:
	    obj1type( int s );
	    ~obj1type();
	
	    void	       *operator new( unsigned int s );
	    void		operator delete( void *mp );
	
	/*    virtual int       can_geometry_obj(); */
	};
	
	class obj2type : public obj1type
	{
	    void *t_tag;
	
	  public:
	    obj2type( int s = 0 );
	    virtual int       can_geometry_obj();
	};
	
	void *obj1type::operator new( unsigned int s )
	{
	    void *ret = new char[s];
	
	    fprintf(stderr, "Obj1type new, this = %x\n", ret);
	    return ret;
	}
	
	obj1type::obj1type( int s )
	{
	    fprintf(stderr, "Obj1type constructor, this = %x\n", this);
	}
	
	obj2type::obj2type( int s ) : obj1type( s )
	{
	    fprintf(stderr, "Obj2type constructor, this = %x\n", this);
	}
	
	int obj2type::can_geometry_obj()
	{
	    return 1;
	}
	
	/*
	int obj1type::can_geometry_obj()
	{
	    return 1;
	}
	*/
	
	void main()
	{
	    obj2type *o = new obj2type( 5 );
	}
	
  One would expect the pointer that is returned by Obj1type new operator to
  be the same as the pointer that is passed to the Obj1type constructor as
  happens when running this program under SGI C++:

	Obj1type new, this = 1000b674
	Obj1type constructor, this = 1000b674
	Obj2type constructor, this = 1000b674

  But running this program on NT C++ we get:

	Obj1type new, this = 131f90
	Obj1type constructor, this = 131f94
	Obj2type constructor, this = 131f90

  I can only suspect that a virtual table pointer consumed the 4 missing bytes
  but when the user wrote his new method he ignores this pointer and allocates
  enough bytes for his slots excluding this virtual table, and more
  interestingly why then Obj2type got the original pointer back?
  Making Obj1type having a virtual method (and table), by un-commenting
  the above commented code, "fix" the problem.

* How one make the system's pipe work in binary mode. I can set stdin/out
  to work in binary mode (using setmode or fdopen) but this is what is
  happening.

  I can do

	program1.exe > binary_data

  and

	program2.exe < binary_data

  but I cannot do

	program1.exe | program2.exe

  Any idea?

* I am getting the following messages from the linker.

		lib -out:O.lib *.obj
	Microsoft(R) Windows NT Librarian Version 2.19
	(C) 1989-1992 Microsoft Corp. All rights reserved.

	OH_features.obj() : error 0123: Can't convert object to Windows NT format
	Extended Error: No such file or directory

	cvtomf() : error : Too many SEGDEF/COMDAT records

  Obviously OH_features.c was compiled with Windows NT C++ compiler (with no
  warnings/errors). Looks like I am overflowing some internal table. Any
  way to fix this?

*  	lib -out:SP.lib bspline\*.obj mspl\*.obj tess\*.obj
  Microsoft(R) Windows NT Librarian Version 2.19
  (C) 1989-1992 Microsoft Corp. All rights reserved.

  bspline\is_srf.obj ()() : warning 0506: ?is_srf_open@@YAHPAUsrf_obj@@@Z multiply defined, defined in bspline\blk_eval.obj ()
  
  There is no is_srf_open in blk_eval.c, only in is_srf.c.

* How can one un-mangle the names printed by lib/link/coff -Dump:
  
  render_defs.obj() : warning 0506: ??0trace_hash_table_type@@QAG@XZ multiply defined, defined in render.obj

  so far I have deciphered the following:

  ??0* - a constructor
  ??1* - destructor (!?)
  ??2* - a new method
  ??3* - a delete method

* Annoying bugs in WinDbg.
  1. Source files in unix format (that is no CRLF, just LF) cannot be read
     into the debugger even though the compiler handles them with no problem.
     Getting a "not text file" error. In NTSD the lines are off if only LF.
  2. 'windbg abcdefgh.exe' is ok but 'windbg abcdefghi.exe' is not. In other
     words, still in the MSDOS 8.3 file name conventions. I can read long
     names from the Program/Load menu with no problem though.

* How do one view local variables in WinDbg or ntsd (. does not work).
  Relevant help does not exists, and intuition (mine at least) was not
  helpful...

thanks

Gershon
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
Gershon Elber                            gershon@cs.utah.edu
Computer Science Department              Fax: (801) 581-5843
University of Utah 84112                 Tel: (801) 585-5635