jason
jason

Reputation: 109

Delphi BluetoothLE WriteCharacteristic Access Violation

This is Delphi 10.1 Berlin (probably unpatched). This code is pretty basic. This code is not stable.

Why?

procedure TBLEEnumerator.WriteToSubScribedCharacteristic(bs: TArray<byte>);
var
  //member ble is an instance of TBluetoothLE
  chr: TBluetoothGattCharacteristic;
begin
  chr := ble.GetCharacteristic(FBLEGattService, ChooseCharacteristic);
  chr.SetValue(bs);
  ble.WriteCharacteristic(self.dev, chr);
end;

A few other notes: This error is when running on Windows, but I intend this code to run also on mobile devices.

This function is called from the Main Thread and is a wrapper around the TBluetoothLE component. The original connection/scan is also handled from the main thread.

It is pretty simple, obviously. TArray is a reference-counted dynamic array.

Here's the call stack when it tanks:

:761d31ce ucrtbase.memcpy + 0x4e
System.Win.BluetoothWinRT.BytesToIBuffer(???,???)
System.Win.BluetoothWinRT.TWinRTBluetoothGattCharacteristic.SetValueToDevice
System.Win.BluetoothWinRT.TWinRTBluetoothLEDevice.DoWriteCharacteristic$52$ActRec.$0$Body
System.Classes.TAnonymousThread.Execute
System.Classes.ThreadProc($7511F40)
System.ThreadWrapper($5A30D30)
:740162c4 KERNEL32.BaseThreadInitThunk + 0x24
:77060fd9 ; 
:77060fa4 ;

Upvotes: 0

Views: 1125

Answers (1)

jason
jason

Reputation: 109

Here's the deal. This is a BUG in the Embarcadero Libraries. Yes, Yet another bug that they will probably never fix.

Here's how to fix it for yourself:

  1. copy System.Win.BluetoothWinRT.pas to your project directory or some other path used by the project.
  2. open the file in the IDE.
  3. Search for "BytestoIBuffer".
  4. Remove the word "const" from the function signature.

Very few people seem to realize this (including the authors of FMX and VCL) but the use of "const" strings and dynamic arrays causes the Win32 compiler to optimize-out the reference count handling for those structures. I don't know if it affects the mobile compilers or the Win64 compiler, but maybe.

The nasty effect of this is that if that string or dynamic array originated from another thread, that other thread might very well decide to destroy that string or dynamic array before the new thread (in this case an anonymous thread created to write-behind the data) is finished working with it.

Removing const from this function fixed the instability.

Upvotes: 1

Related Questions