Recent

Author Topic: string pointers behaves different in loop  (Read 16104 times)

Goodman H__

  • Full Member
  • ***
  • Posts: 130
string pointers behaves different in loop
« on: August 24, 2010, 04:53:52 am »
Greeings,

I am so excited that pointers in fp have the same power as in C.Considering below code:
Code: [Select]
procedure TestPointer;
var
  str:string;
  pstr:pstring;
begin
 
  str:='This is a very very long string that test string pointers';
  pstr:=@str;
  while true do
  begin
       write(pstr^+' ');
       pstr:=pstr+1;
       if pstr=nil then break;
  end;
  writeln;

end;        


Using the above while...do loop I got an exception after the correct output.The error message is:
Code: [Select]
Project project1.exe raised exception class 'External:SIGSEGV'.

But when I use repeat ...until loop it works fine with no problem:
Code: [Select]
...
 repeat
       write(pstr^+' ');
       pstr:=pstr+1;
  until pstr<>nil;
...

So I am really confused what's the logic problem in the while...do loop solution which caused the exception.

It would be grateful if you would like to help.          
« Last Edit: August 24, 2010, 04:59:14 am by Goodman H__ »
fpc:2.6.1 Lazarus:1.1 SVN39277
OS:win 7

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: string pointers behaves different in loop
« Reply #1 on: August 24, 2010, 06:31:01 am »
String is an opaque type. It's a simple array of char in default mode, but pointer to a record (with a longint indicating the length, and a dynamic array containing the characters) in objfpc and delphi mode. I don't recommend using pointers to strings at all. Use var parameters instead.

Goodman H__

  • Full Member
  • ***
  • Posts: 130
Re: string pointers behaves different in loop
« Reply #2 on: August 24, 2010, 09:29:40 am »
String is an opaque type. It's a simple array of char in default mode, but pointer to a record (with a longint indicating the length, and a dynamic array containing the characters) in objfpc and delphi mode. I don't recommend using pointers to strings at all. Use var parameters instead.

Thanks for the reply.My first intention to use pointers to strings is the compatability and  performance as c to interact with OS calls with the power of pointer arithmetic operations.

Can I ask what you mean by 'use var parameters instead', a piece of code segment please?
« Last Edit: August 24, 2010, 09:45:03 am by Goodman H__ »
fpc:2.6.1 Lazarus:1.1 SVN39277
OS:win 7

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: string pointers behaves different in loop
« Reply #3 on: August 24, 2010, 10:42:01 am »
You can use the PChar type which is exactly the same as char* in C.
You can convert String <> Pchar like:

APChar:=PChar(AStr);
AStr:=APChar; 

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: string pointers behaves different in loop
« Reply #4 on: August 24, 2010, 10:58:48 am »
I think  it is pure luck that the repeat doesn't crash.

 if pstr=nil then break;
  until pstr<>nil;

pstr may be nil (if the string is empty to begin with). so you must test upfront

pstr will not become nil, if you reach the end of the str.

if pstr^ = #0 then

should help

Goodman H__

  • Full Member
  • ***
  • Posts: 130
Re: string pointers behaves different in loop
« Reply #5 on: August 25, 2010, 02:35:12 am »
I think  it is pure luck that the repeat doesn't crash.

 if pstr=nil then break;
  until pstr<>nil;

pstr may be nil (if the string is empty to begin with). so you must test upfront

pstr will not become nil, if you reach the end of the str.

if pstr^ = #0 then

should help

Thanks a lot.After tried several time with all the above possibilities,I am getting more and more confused.For example,if pstr^=#0 then almost leads to the same result as pstr=nil,so I am so confused with pointers to strings...Studying...

fpc:2.6.1 Lazarus:1.1 SVN39277
OS:win 7

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: string pointers behaves different in loop
« Reply #6 on: August 25, 2010, 02:53:49 am »
Another possible mistake from your original post:

 pstr:=@str;

This may not may not give you a pointer to the chars in the string.

Depending on compiler settings, string is either:
shortstring
ansistring

shortstring always has a fixed length, and therefore a shortstring can be at a fixed (and known at compile time) location in memory.

Ansistring can grow to any size. Memory must be allocated on the fly, once the required amount is known. That means behind the scenes ansistring must do memory management too. And store that info.
AnsiString is internally already a pointer, but normally you never will notice.

var
  sa: AnsiString;
  sb: ShortString[10];

pa := @sa;  // something you never want. a pointer to an internal structure of fpc, may change in new fpc versions, not save to access

pa := @sa[1]; // works, but gives a range check, if the string is empty

pa := Pchar(sa); // always good

pb := @sb; // may work, I don't actually know
pb := @sb[1]; //ok, as long as sb was defined with a len of 1 or more
pb := pchar(pb); // good

pa can be nil, if the sa was empty. That may be unexpected, because you can't do "if pa^ = #0"

since the shortstring has a fixed len pb should never be nil


marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11459
  • FPC developer.
Re: string pointers behaves different in loop
« Reply #7 on: August 25, 2010, 06:52:25 am »
Whatever the type is,  shortstring or ansistring, incrementing it is never a good idea.  >:D

Even compatibility with C doesn't require pointers. You can perfectly pass an ansistring (read-only) to a C routine.

So maybe you should explain better what exactly you want to accomplish.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: string pointers behaves different in loop
« Reply #8 on: August 25, 2010, 07:35:54 am »
Quote
My first intention to use pointers to strings is the compatability and  performance as c to interact with OS calls with the power of pointer arithmetic operations.
Pascal strings are actually more powerful and easier to use than C strings (for example, getting string length through strlen() has a complexity of O(n) while Pascal's Length() is only O(1)). Most things can be done without pointers in Pascal, you only need it in rare cases.
Quote
Can I ask what you mean by 'use var parameters instead', a piece of code segment please?
Well, if you're using pointers because you want to pass parameters as efficient as possible, then using var (or const) parameters will do the same. Example:
Code: [Select]
// when you call this, a copy of the string will be passed
procedure DoSomethingWithString(s: string);
begin
  s := '';
end;
// when you call this, pointer to the string will be passed
// but you still access is the same way as above.
// use const instead of var to make it readonly but still retaining the efficiency
procedure DoSomethingElseWithString(var s: string);
begin
  s := '';
end;

Goodman H__

  • Full Member
  • ***
  • Posts: 130
Re: string pointers behaves different in loop
« Reply #9 on: August 25, 2010, 08:07:16 am »
Whatever the type is,  shortstring or ansistring, incrementing it is never a good idea.  >:D

Even compatibility with C doesn't require pointers. You can perfectly pass an ansistring (read-only) to a C routine.

So maybe you should explain better what exactly you want to accomplish.

for example:
Code: [Select]
typedef struct Stuff__
{
    Stuff__ *next;
    Stuff__ *previous;
    char ***matrix;
}Stuff;
Maybe I would like to matrix to do some rotation operations.And the Stuff should do some basic concatenations the like.
« Last Edit: August 25, 2010, 08:21:38 am by Goodman H__ »
fpc:2.6.1 Lazarus:1.1 SVN39277
OS:win 7

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11459
  • FPC developer.
Re: string pointers behaves different in loop
« Reply #10 on: August 25, 2010, 08:40:56 am »
[

for example:
Code: [Select]
typedef struct Stuff__
{
    Stuff__ *next;
    Stuff__ *previous;
    char ***matrix;
}Stuff;
Maybe I would like to matrix to do some rotation operations.And the Stuff should do some basic concatenations the like.

matrix is a pointer to pointer to pointer to char.  But it can be seen as a two dimensional grid of strings, or and array of pointers to 8-bit images.

But in general, optimizing strings to the pointer level does not bring much. This because (ansi)strings are already basically only a small abstraction over array pointers. Because the copy-on-write and length field they can even be faster than naieve array pointer usage.

So assuming you meant a two dimensional matrix of strings, try

Code: [Select]
Type
    PStuff = ^Stuff;
    Stuff = record
      next,
      previous  : PStuff;
      Matrix     : array of array of ansistring; // or just a. of a. of string in Delphi mode
     end;

Besides the string abstraction, this also uses the dynamic array abstraction, which you can read about here:

http://www.freepascal.org/docs-html/ref/refsu14.html#x38-420003.3.1

Goodman H__

  • Full Member
  • ***
  • Posts: 130
Re: string pointers behaves different in loop
« Reply #11 on: August 25, 2010, 10:20:10 am »
[

for example:
Code: [Select]
typedef struct Stuff__
{
    Stuff__ *next;
    Stuff__ *previous;
    char ***matrix;
}Stuff;
Maybe I would like to matrix to do some rotation operations.And the Stuff should do some basic concatenations the like.

matrix is a pointer to pointer to pointer to char.  But it can be seen as a two dimensional grid of strings, or and array of pointers to 8-bit images.

But in general, optimizing strings to the pointer level does not bring much. This because (ansi)strings are already basically only a small abstraction over array pointers. Because the copy-on-write and length field they can even be faster than naieve array pointer usage.

So assuming you meant a two dimensional matrix of strings, try

Code: [Select]
Type
    PStuff = ^Stuff;
    Stuff = record
      next,
      previous  : PStuff;
      Matrix     : array of array of ansistring; // or just a. of a. of string in Delphi mode
     end;

Besides the string abstraction, this also uses the dynamic array abstraction, which you can read about here:

http://www.freepascal.org/docs-html/ref/refsu14.html#x38-420003.3.1

This is awesome.

From the dynamic array what I understand is there is an expensive cost everytime the array need resize,but pointers doesn't.Please correct me if I am wrong.Thanks.
fpc:2.6.1 Lazarus:1.1 SVN39277
OS:win 7

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11459
  • FPC developer.
Re: string pointers behaves different in loop
« Reply #12 on: August 25, 2010, 03:08:52 pm »
From the dynamic array what I understand is there is an expensive cost everytime the array need resize,but pointers doesn't.Please correct me if I am wrong.Thanks.

You are wrong. There is a minimal, insignificant overhead at best. Moreover it is only noticable in the tightest of loops that you can optimize afterwards by, in the tightest loop, _locally_ iterating with pointers through the dyn array.

So just use dyn arrays, and forget the rest till really needed.

Goodman H__

  • Full Member
  • ***
  • Posts: 130
Re: string pointers behaves different in loop
« Reply #13 on: August 26, 2010, 02:45:08 am »
From the dynamic array what I understand is there is an expensive cost everytime the array need resize,but pointers doesn't.Please correct me if I am wrong.Thanks.

You are wrong. There is a minimal, insignificant overhead at best. Moreover it is only noticable in the tightest of loops that you can optimize afterwards by, in the tightest loop, _locally_ iterating with pointers through the dyn array.

So just use dyn arrays, and forget the rest till really needed.

Thank you so much.I should study deeper in FP's memory model.
fpc:2.6.1 Lazarus:1.1 SVN39277
OS:win 7

 

TinyPortal © 2005-2018