Thread overview
size_t, size_t, wherefore art thou aliased?
Sep 20, 2006
Gregor Richards
Sep 20, 2006
Lionello Lunesu
Sep 20, 2006
Gregor Richards
Sep 21, 2006
Steve Horne
Sep 21, 2006
Hasan Aljudy
Sep 23, 2006
Frank Benoit
September 20, 2006
(For the early-modern-English-impaired, "wherefore art thou aliased" means "why are you aliased")

In the process of porting GDC to x86_64 (which has actually been somewhat successful, but more on that later), I've discovered what I consider to be a fairly significant problem.

Because size_t is aliased (and also partially because DDoc follows aliases apparently), there is a tendency to use uint instead of size_t, and no error or even feedback if you do!

For example, std.socketstream overrides:

size_t readBlock(void* _buffer, size_t size)

with

uint readBlock(void* _buffer, uint size)

Ouch!  Works fine on 32-bit systems, but totally fails on 64-bit systems, and the writer has no way of knowing there's a bug until he tries to compile it on a 64-bit system!  The biggest problem here is with overriding (as in the above example), where it'll override properly on 32-bit but improperly on 64-bit systems.

The folks on #d and I have created several possible solutions.

Our original thought was to make size_t (and ptrdiff_t) typedefs instead of aliases - this would at least require no change to the language proper.  Unfortunately, this makes assigning values to size_t and ptrdiff_t obnoxious, since it only implicitly casts one way (not the way that's helpful here).

Secondly, size_t and ptrdiff_t could be compiler-defined types, rather than aliased types.  This would make the implicit casting come out right, but is sort of ugly.

Finally, the preferred option seems to be a sort of weak typedef. Basically, this would be a typedef, but with implicit casting both ways.  So, [u]ints, [u]longs, size_ts and ptrdiff_ts would all play nicely together, but overrides would not be happy if improperly defined.

The most unfortunate thing about this is that there's virtually no way for a programmer on a 32-bit system to know when they've ran into a bug like this.  Yuck.

 - Gregor Richards
September 20, 2006
> Unfortunately, this makes assigning values to size_t and ptrdiff_t obnoxious, since it only implicitly casts one way (not the way that's helpful here).

typedef int test_t;
void main(){
  test_t x = 2;
}

works just fine. Am I missing something?

L.


September 20, 2006
Lionello Lunesu wrote:
>> Unfortunately, this makes assigning values to size_t and ptrdiff_t obnoxious, since it only implicitly casts one way (not the way that's helpful here).
> 
> typedef int test_t;
> void main(){
>   test_t x = 2;
> }
> 
> works just fine. Am I missing something?
> 
> L. 
> 
> 

typedef int test_t;

int main()
{
    test_t x;
    int y = 2;
    x = y;
    return 0;
}


Actually, the absolutely precise solution would be a precise reversal of the typedef rules - size_t should accept ints/longs/etc, but ints/longs/etc should not accept size_t.

 - Gregor Richards
September 21, 2006
On Wed, 20 Sep 2006 08:15:29 -0700, Gregor Richards <Richards@codu.org> wrote:

>The most unfortunate thing about this is that there's virtually no way for a programmer on a 32-bit system to know when they've ran into a bug like this.  Yuck.

In Visual C++, you get warnings about size issues even when they don't exist. VC++ will complain if it thinks the type you specified might be a 64 bit type in the future, and your using it somewhere 32-bitty for instance.

Maybe a similar (optional) compiler warning? The compiler could flag 'this is being treated as an uint32_t/uint64_t but it was originally size_t' and give warnings as needed?

-- 
Remove 'wants' and 'nospam' from e-mail.
September 21, 2006
I think I don't really understand the issue, but I'm gonna throw in my 2 cents anyway ... even though it might sound pretty stupid:

Wouldn't a versioned alias declaration solve this?

version( X32 )
{
  alias something ...
}
version( X64 )
{
  alias something else ...
}

Gregor Richards wrote:
> (For the early-modern-English-impaired, "wherefore art thou aliased" means "why are you aliased")
> 
> In the process of porting GDC to x86_64 (which has actually been somewhat successful, but more on that later), I've discovered what I consider to be a fairly significant problem.
> 
> Because size_t is aliased (and also partially because DDoc follows aliases apparently), there is a tendency to use uint instead of size_t, and no error or even feedback if you do!
> 
> For example, std.socketstream overrides:
> 
> size_t readBlock(void* _buffer, size_t size)
> 
> with
> 
> uint readBlock(void* _buffer, uint size)
> 
> Ouch!  Works fine on 32-bit systems, but totally fails on 64-bit systems, and the writer has no way of knowing there's a bug until he tries to compile it on a 64-bit system!  The biggest problem here is with overriding (as in the above example), where it'll override properly on 32-bit but improperly on 64-bit systems.
> 
> The folks on #d and I have created several possible solutions.
> 
> Our original thought was to make size_t (and ptrdiff_t) typedefs instead of aliases - this would at least require no change to the language proper.  Unfortunately, this makes assigning values to size_t and ptrdiff_t obnoxious, since it only implicitly casts one way (not the way that's helpful here).
> 
> Secondly, size_t and ptrdiff_t could be compiler-defined types, rather than aliased types.  This would make the implicit casting come out right, but is sort of ugly.
> 
> Finally, the preferred option seems to be a sort of weak typedef. Basically, this would be a typedef, but with implicit casting both ways.  So, [u]ints, [u]longs, size_ts and ptrdiff_ts would all play nicely together, but overrides would not be happy if improperly defined.
> 
> The most unfortunate thing about this is that there's virtually no way for a programmer on a 32-bit system to know when they've ran into a bug like this.  Yuck.
> 
>  - Gregor Richards
September 23, 2006
Hasan Aljudy schrieb:
> I think I don't really understand the issue, but I'm gonna throw in my 2 cents anyway ... even though it might sound pretty stupid:
> 
> Wouldn't a versioned alias declaration solve this?
> 
> version( X32 )
> {
>   alias something ...
> }
> version( X64 )
> {
>   alias something else ...
> }
> 

I think this is exactly like size_t is defined. And the problem Gregor describes is a result from that.