STRPTR returning zero

Forum for discussion about the documentation project.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: STRPTR returning zero

Post by caseih »

dkl wrote:I don't really see a problem, maybe a small inconsistency at best...

Printing *myStringPtr or *myZstringPtr will call the Print function and pass the string Byref, and as it happens, it checks for NULL, and prints nothing in that case. That's a pretty good way of dealing with that problem, don't you think? Alternatively it could crash, or print something like "(null)" like some CRTs' printf() does. But that seems worse to me than printing nothing.
That's interesting. I can indeed pass a NULL to printf() and it prints out "(null)" but when I pass an empty, dynamic string I get a sefault:

Code: Select all

#include "crt.bi"
dim as zstring ptr b
dim as string g

b = 0
printf(!"%s\n",b)
printf(!"%s\n",g)
I wonder why that is.

I'm not convinced printing nothing for a null pointer is the best way of dealing with the problem. If you're trying to print out a string that's really a null pointer, that's likely an error in your code somewhere, one that is hidden until it finally blows up in some C library.

EDIT. I see why it segfaults. There is a dereference in the C code emitted by the computer, before it even gets to printf.
fxm
Moderator
Posts: 12131
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: STRPTR returning zero

Post by fxm »

Works with gas.
Output:

Code: Select all

(null)
(null)
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: STRPTR returning zero

Post by Tourist Trap »

fxm wrote:

Code: Select all

i = *pi  '' runtime error 7 (null pointer access)
z = *pz  '' ok
I don't have too much opinion about what could be the problems with some dependancies, written in C or else. But thinking again of this example above, I've found one reason for which it seems consistent for the strings to be set to "" if we want to keep in dereference a null pointer. It has no consequencies because the only operator with strings is concatenation. And "" is neutral for concatenation, it won't really affect it in a way or an other.
We can't say the same with integers of the example. 0 would be ok for the addition, but would make multiplication quite unhappy. So there is no way to decide what harmless value to assign if we wanted absolutely one for *pi.
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: STRPTR returning zero

Post by dkl »

Well, here with -gen gcc the printf("%s\n", s) is turned into puts(s) by gcc, and puts(NULL) crashes. That's one of those cases where C undefined behaviour leaks into FB due to -gen gcc.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: STRPTR returning zero

Post by caseih »

Interesting. On Linux, it's definitely using printf still:

Code: Select all

printf( (uint8*)"%s\x0A", *(uint8**)&G$0 );
G$0 is the "g" variable in my last post.
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: STRPTR returning zero

Post by dkl »

I found it when running in valgrind and then looking at .asm output produced by gcc (fbc -gen gcc -RR) to confirm. There was a printf() in the C code generated by fbc, as expected, but then gcc compiled it to puts().
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: STRPTR returning zero

Post by caseih »

A recent message about using GTK on this forum reinforced to me the need to change FB's dynamic string behavior. The user in that post was using strptr to get a pointer to the string, but of course he needn't have done that as he could just pass FB strings directly to the GTK call and FBC would convert it to a zstring ptr on the fly. Except if the string is empty. There are good reasons to pass empty strings (no characters other than the null terminator) to a library like GTK. But currently FB will not do this. It will pass a NULL instead. This probably won't crash GTK since it's pretty fault tolerant and looks for NULLS, but it certainly wouldn't do the right thing. We touched on this a few posts ago:

Code: Select all

#include "crt.bi"
dim as string b
b=""
printf("%s\n",b)
Assuming this wouldn't sefgault, printf defaults, as you said, to printing "(null)" but in this code that's not what we wanted. We wanted to print nothing but a newline. Now obviously this is a contrived example and almost no one would ever do this. But as I said, it's not unknown to pass an empty string to things in external libraries. In FB this is not possible if the programmer is using a dynamic string. This is something that would be fairly easy to fix without breaking anything. If I have time I'll give it a go and open a bug ticket with a potential patch.

I see two solutions. One is to allocate the standard amount of memory when a string is created and a dynamic string will never have less than the default allocation (same as if you said b = "1").

The other solution is to have a static piece of memory that contains nothing but a NULL that when a string is made to be empty, the .data part of the descriptor points to this static memory. Later when the string is modified, memory is allocated normally.
fxm
Moderator
Posts: 12131
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: STRPTR returning zero

Post by fxm »

Code: Select all

#include "crt.bi"

dim as string b = ""
print "string descriptor",cptr(uinteger ptr,@b)[0],cptr(uinteger ptr,@b)[1],cptr(uinteger ptr,@b)[2]

b=chr(0)
print "string descriptor",cptr(uinteger ptr,@b)[0],cptr(uinteger ptr,@b)[1],cptr(uinteger ptr,@b)[2]

cptr(uinteger ptr,@b)[1]=0
print "string descriptor",cptr(uinteger ptr,@b)[0],cptr(uinteger ptr,@b)[1],cptr(uinteger ptr,@b)[2]

printf(!"%s\n",b)
printf(!"%s\n","Passed above an empty zstring to printf!")

print "string descriptor",cptr(uinteger ptr,@b)[0],cptr(uinteger ptr,@b)[1],cptr(uinteger ptr,@b)[2]

b=""
print "string descriptor",cptr(uinteger ptr,@b)[0],cptr(uinteger ptr,@b)[1],cptr(uinteger ptr,@b)[2]

sleep

Code: Select all

string descriptor           0             0             0
string descriptor           6369080       1             36
string descriptor           6369080       0             36

Passed above an empty zstring to printf!
string descriptor           6369080       0             36
string descriptor           0             0             0
Post Reply