Ugochukwu Mmaduekwe 42 Posted November 21, 2018 Hi all, I wrote a simple function to help me convert a string to an array of char but I keep getting random occurring access violations. class function TUtilities.StringToCharArray(const S: String) : TCharArray; begin if System.Length(S) > 0 then begin System.SetLength(Result, System.Length(S)); StrPLCopy(PChar(Result), S, System.Length(Result)); end; end; Anyone know the cause? Thanks. Share this post Link to post
Attila Kovacs 629 Posted November 21, 2018 (edited) it's in the help Note: Dest should point to a location with room for MaxLen + 1 characters, including the null terminator. too bad that the compiler can't detect the out of range Edited November 21, 2018 by Attila Kovacs 1 Share this post Link to post
Guest Posted November 21, 2018 You should try this class function TUtilities.StringToCharArray(const S: String) : TCharArray; begin System.SetLength(Result, System.Length(S)); if System.Length(S) > 0 then begin StrPLCopy(PChar(Result), S, System.Length(Result)); end; end; Share this post Link to post
Ugochukwu Mmaduekwe 42 Posted November 21, 2018 5 hours ago, Attila Kovacs said: it's in the help Note: Dest should point to a location with room for MaxLen + 1 characters, including the null terminator. too bad that the compiler can't detect the out of range Thanks a lot, this did solve the problem. Share this post Link to post
Ugochukwu Mmaduekwe 42 Posted November 21, 2018 35 minutes ago, Schokohase said: You should try this class function TUtilities.StringToCharArray(const S: String) : TCharArray; begin System.SetLength(Result, System.Length(S)); if System.Length(S) > 0 then begin StrPLCopy(PChar(Result), S, System.Length(Result)); end; end; unfortunately, this did not work, but thanks either way. Share this post Link to post
David Heffernan 2345 Posted November 21, 2018 You write a zero byte beyond the end of the char array. Solve the problem by using Move to perform the copy. 1 Share this post Link to post
KodeZwerg 54 Posted November 21, 2018 (edited) *removed, error* Edited November 21, 2018 by KodeZwerg Share this post Link to post
KodeZwerg 54 Posted November 21, 2018 (edited) 2 hours ago, Ugochukwu Mmaduekwe said: System.SetLength(Result, System.Length(S)); This should be SetLength(Result, Length(S) * SizeOf( AnsiChar ) ); program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; function MyStringToMyCharArray( const S: String ): TCharArray; begin SetLength(Result, Length(S) * SizeOf( AnsiChar ) ); if Length( S ) > 0 then begin StrPLCopy( PChar( Result ), S, Length( Result ) ); end; end; var S: String; C: TCharArray; I: Integer; begin try { TODO -oUser -cConsole Main : Insert code here } S := 'My Test String'; C := MyStringToMyCharArray( S ); for i := 0 to Length( C ) -1 do write( c[ i ] ); writeln; readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Edited November 21, 2018 by KodeZwerg Share this post Link to post
Kryvich 165 Posted November 21, 2018 function StringToCharArray(const S: string): TCharArray; begin PChar(Result) := PChar(S); end; 1 Share this post Link to post
Guest Posted November 21, 2018 (edited) Option 1 uses System.SysUtils; class function TUtilities.StringToCharArray(const S: String) : TCharArray; begin Result := S.ToCharArray(); end; Option 2 (found at System.SysUtils.TStringHelper.ToCharArray from Delphi 10.2.3 Tokyo) class function TUtilities.StringToCharArray(const S: String) : TCharArray; begin SetLength(Result, Length(S)); Move(PChar(PChar(S))^, Result[0], Length(S) * SizeOf(Char)); end; Edited November 21, 2018 by Guest Share this post Link to post
Ugochukwu Mmaduekwe 42 Posted November 21, 2018 43 minutes ago, KodeZwerg said: This should be SetLength(Result, Length(S) * SizeOf( AnsiChar ) ); program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; function MyStringToMyCharArray( const S: String ): TCharArray; begin SetLength(Result, Length(S) * SizeOf( AnsiChar ) ); if Length( S ) > 0 then begin StrPLCopy( PChar( Result ), S, Length( Result ) ); end; end; var S: String; C: TCharArray; I: Integer; begin try { TODO -oUser -cConsole Main : Insert code here } S := 'My Test String'; C := MyStringToMyCharArray( S ); for i := 0 to Length( C ) -1 do write( c[ i ] ); writeln; readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. This will give the same access violation as the previous one if you run it multiple times in a loop. The +1 space for the null terminator still applies. Share this post Link to post
Ugochukwu Mmaduekwe 42 Posted November 21, 2018 26 minutes ago, Kryvich said: function StringToCharArray(const S: string): TCharArray; begin PChar(Result) := PChar(S); end; Oddly enough, this seems to work. Another function in my arsenal. Thanks. Share this post Link to post
Fritzew 51 Posted November 21, 2018 45 minutes ago, KodeZwerg said: This should be SetLength(Result, Length(S) * SizeOf( AnsiChar ) ); Can you tell us why you think these is right? There is no reason for this construct. Length(s) is enough . 1 Share this post Link to post
Ugochukwu Mmaduekwe 42 Posted November 21, 2018 8 minutes ago, Schokohase said: Option 1 uses System.SysUtils; class function TUtilities.StringToCharArray(const S: String) : TCharArray; begin Result := S.ToCharArray(); end; Option 2 (found at System.SysUtils.TStringHelper.ToCharArray) class function TUtilities.StringToCharArray(const S: String) : TCharArray; begin SetLength(Result, Length(S)); Move(PChar(PChar(S))^, Result[0], Length(S) * SizeOf(Char)); end; Thanks but am trying to avoid the string helper functions, I also want to avoid using *move* on strings because I heard some time back that it breaks reference counting on strings. Share this post Link to post
Kryvich 165 Posted November 21, 2018 @Ugochukwu Mmaduekwe Delphi can convert a string to PChar, and PChar to TCharArray. Share this post Link to post
Cristian Peța 103 Posted November 21, 2018 1 hour ago, Ugochukwu Mmaduekwe said: Thanks but am trying to avoid the string helper functions, I also want to avoid using *move* on strings because I heard some time back that it breaks reference counting on strings. It can brake reference counting only if you move() to string. When you only move() from string the string is not affected in any way. Move() doesn't change the source. 1 1 Share this post Link to post
Ugochukwu Mmaduekwe 42 Posted November 21, 2018 (edited) 14 minutes ago, Cristian Peța said: It can brake reference counting only if you move() to string. When you only move() from string the string is not affected in any way. Move() doesn't change the source. Thanks a lot for the explanation. Edited November 21, 2018 by Ugochukwu Mmaduekwe Share this post Link to post