1

I want to do the following but I get "Access violation" error.

type Bin = array of byte;

var s:string;

begin
 s:='some string';
 Bin(s)[3]:=ord('X');
 caption:=s;
end;

Why this doesn't work ?

mghie
  • 32,028
  • 6
  • 87
  • 129
Marus Gradinaru
  • 2,824
  • 1
  • 26
  • 55
  • Why do you want to? You can simply access `s[3]` directly - there's no need for the `array of byte` here at all. – Ken White Jun 12 '14 at 19:54
  • Very hard to know what you are trying to do. Not least because we don't know what string is. UnicodeString or AnsiString? – David Heffernan Jun 12 '14 at 19:56
  • @SertacAkyuz, yes var "s" it's local. @KenWhite, I want to do some work with the bytes of the string (encription algorithm) without the need to convert the char to byte with the `ord()` function and back to char with the `chr()` function. @DavidHeffernan, it is an AnsiString – Marus Gradinaru Jun 12 '14 at 20:04
  • How is this question not a duplicate of [Using AnsiString like byte of array in Delphi XE4](http://stackoverflow.com/q/20611507) or [How to convert strings to array of byte and back](http://stackoverflow.com/q/21442665) then? – Ken White Jun 12 '14 at 20:11
  • 1
    How about `RawByteString`? – Free Consulting Jun 12 '14 at 21:25
  • RawByteString won't help here in ANSI Delphi 'cos it ain't there. And it's no good in Unicode Delphi either. Why run the gauntlet of text encodings and potential for conversion when you are working with binary data. Encryption 101, don't operate on text. – David Heffernan Jun 13 '14 at 07:28
  • There is no obvious indication what it is related to pre-Unicode Delphi. – Free Consulting Jun 13 '14 at 12:38
  • It is clearly stated in the comments that this is pre-Unicode Delphi. – David Heffernan Jun 15 '14 at 15:04

1 Answers1

6

This does not work because AnsiString and a dynamic array of byte are incompatible types. Your cast is invalid and anything can happen.

As it turns out, your string is a literal. The compiler handles that by putting the string in read only memory. Hence the access violation when you go behind its back.

The solution is easy enough. Use the [] indexing operator on the string directly:

s[i] := ...;

When you do this, the compiler knows that the string is read-only, and copies it to writeable memory to allow you to modify it.

You say that you don't want to use ord() and chr(). I don't know why. They are the correct things to use and, it's not as if they even result in any code being emitted. They are intrinsics that turn into no-ops.

You state in a comment that you are coding an encryption algorithm. This then points up the fundamental flaw in your approach. Encryption algorithms operate on byte arrays. Don't feed text into an encryption code. Convert to a byte array using some well-defined text encoding. And then operate on byte arrays. And don't reinvent the wheel. Use an existing crypto library.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Please tell me if I understand corectly. You said that `ord()` and `chr()` are not normal functions and no code is generated for then ? Because I need to use them a lot and I was afraid to not slow down the program. – Marus Gradinaru Jun 12 '14 at 21:39
  • 2
    They are intrinsics and since they can be written as no-ops I expect they are. But you are missing the point. Stop using strings as a data type for encryption. Encrypt byte arrays. That's the beginning and the end of it. And when you ever care about performance don't guess. Measure. – David Heffernan Jun 12 '14 at 21:47