Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/RTL/Delphi/Other Classes    [ Add a report in this area ]  
Report #:  108978   Status: Closed
[Regression in XE3] TStream.Write produces AV in some cases
Project:  Delphi Build #:  17.0.4625.53395
Version:    17.0 Submitted By:   Max Rusov
Report Type:  Crash / Data loss / Total failure Date Reported:  9/24/2012 8:25:13 AM
Severity:    Critical / Show Stopper Last Updated: 9/26/2012 6:36:59 AM
Platform:    All versions Internal Tracking #:   32232
Resolution: Test Case Error (Resolution Comments) Resolved in Build: : None
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: 12
Description
This code work fine on previous version Delphi.
On XE3, it produces Access Violation.

----------
  procedure Test;
  var
    vStream :TMemoryStream;
    vList :TList;
  begin
    vStream := TMemoryStream.Create;
    try
      vList := TList.Create;
      try
        vList.Add(pointer(1));
        vStream.Write(vList.List[0], vList.Count * Sizeof(Pointer));  // AV
      finally
        vList.Free;
      end;
    finally
      vStream.Free;
    end;
  end;
----------

Possible, compiler choose wrong overriden method Stream.Write
Steps to Reproduce:
None
Workarounds
None
Attachment
None
Comments

Rob Kennedy at 9/25/2012 6:54:04 AM -
This is probably because of the addition of an overloaded Write function that accepts TBytes. In XE2 and earlier, TStream only had one Write method. Now, the compiler prefers to assign Pointer-typed expressions to the TBytes parameter instead of the untyped parameter (which makes sense, since Pointer has always been assignment-compatible with dynamic arrays).

Definitely a regression, though, since there's no way for the compiler to distinguish new code that intentionally converts Pointer to TBytes from old code that expected to pass the Pointer as an untyped parameter, and so there's no way for the compiler to warn that anything might be wrong.

Tomohiro Takahashi at 9/26/2012 5:59:41 PM -
This is a comment from internal tracking system.
<<<<<<<<<<
This test case is incorrect. Previously, there was a function in the stream that accepted a pointer to store, and instead of storing the contents, stored the address value. This is fixed in XE3. If you pass a pointer, the compiler decides what function needs to be used, but those function expect a correct pointer value.
The construct that you used in the sample is no longer valid, an in essence is totally wrong.
>>>>>>>>>>

Dmitry Burov at 9/28/2012 7:38:22 AM -
TList items, while formally pointers, traditionally been used to store any kind of ordinal data.
Until Delphi 2009 there where not much containers and even in 2009 they were unusable. Keeping values from TList might be perfectly valid, assuming that data are integer or char or set really.

Just like TComponent.Tag been formally Integer used to keep any data like pointer or whatever.

Max Rusov at 9/28/2012 8:04:44 AM -
The problem is that the behavior of TStream.Write has radically changed.
We got a lots of mistakes in the legacy code.

Server Response from: ETNACODE01