Author: Robert Hyatt
Date: 19:49:55 09/05/05
Go up one level in this thread
On September 05, 2005 at 19:17:33, Carey wrote: >On September 05, 2005 at 18:01:27, Robert Hyatt wrote: > >>On September 05, 2005 at 16:58:01, Carey wrote: >> >>>On September 05, 2005 at 14:44:58, Robert Hyatt wrote: >>> >>>> >>>> void *p = (void *) ((int) malloc(size+63) + 63) & ~63); >>>> >>>>What I do is malloc 63 bytes more than I need, add 63 to the resulting pointer, >>>>then and with a constant (an int unfortunately) that has the rightmost 6 bits >>> >>>I always did that seperately. Allocate it and then cast to unsigned int, and >>>then masked off how much I needed, then added that to the original pointer. >>>That way the pointer never had a chance to be truncated. >> >>Sorry. "cast to unsigned int" casts a 64 bit value to a 32 bit value. You just >>lost the upper 32 bits... Remember that _any_ int on these compilers is 32 >>bits. While pointers in 64 bit mode are 64 bits long. Any conversions will >>completely wreck an address (pointer). > > >Right. But that's not what I said. Or at least not what I meant. Rereading it >I can see how you misread what I said. > >You are doing the whole thing as a single statement. That's the problem. You >are trying to do too much at once. > >I said to do it seperately. > >Leave the malloc return as a pointer. This part never gets chopped to any >integer. It stays safe. > >Then seperately, we cast it to an int. Or even a char. Just enough we can do >the alightment. The loss in precision there is irrelevant because we are >working with small integer (a few bits) anyway. > >Then we take that very small integer adjustment and add that to the original >pointer. That type of adjustment is perfectly safe. No different from doing >any of the normal pointer math, such as ptr=ptr+1; Perhaps. I see what you are saying, but the only risk is that it is not possible to add ptr = ptr + int without some re-casting to get rid of the warnings/errors. And there is a potential problem. > >That way the pointer itself never ever gets cast to an int. It always stays as >the full pointer. Only the adjustment calculation part ever gets chopped to an >int, and in that case, it's okay. All we are needing is a few bits anyway. > >This is identical to what we used to have to do back in the days of 16 bit DOS >when mixing 16 bit near vs. 20/32 bit 'huge' &'far' vs. 32 bit flat pointers. >(Although back in those days, we had to do a bit of extra work to make sure the >pointers were normalized, etc.) > >We used to do wrapper routines. (Sometimes macros, but usually functions.) >Something like: > >void *AlignedMalloc(size_t Bytes) >{unsigned int a; > unsigned char *ptr; >/* for proper official standard behavior, must be unsigned char */ > >ptr=(unsigned char*)malloc(Bytes+64); >a=(unsigned int)ptr; >a= a & 63; >a=64-a; >ptr = ptr + a; >return (void *)Ptr; >} > >As you can see, the pointer is never at risk from being chopped. Back in the >old days, we never really knew what size pointer we'd be working with. It might >be compiled with 16 bit pointers, or 32 bit 'far'/'huge' pointers, or even on a >full brand new 32 bit 386 system. Right. only issue is the warning / error since adding a 64 bit pointer and a 32 bit integer is not permissable... > >(Actually, there are other, technically better, ways to do that function. This >assumes that a char is a byte is a cell, and so on. It wont work right on some >exotic systems. For those, it might be safer to just increment the pointer up >to 64 times until the lower bits show it's aligned. If it hasn't done it by >then, you give a fatal error becuase you are on a really weird system.) > >Of course, we also did similar things for calloc, etc. > >And, of course, doing a 'free' was more than a little difficult, since the >original pointer was lost. This could be dealt with by storing it, or by just >not caring and letting the OS free the memory when we were done. > I saved the original when doing this in Crafty. I no longer do it since I allocate memory differently (shmget()) which only allocates memory starting on a page boundary anyway... > >>>>32 bits, pointer (and long) = 64 bits... Why an int is 32 bits on a 64 bit >>>>machine is a good question. We really needed some better int types, but the >>> >>>Up to the compiler designer. >>> >>>Realistically, it makes quite a bit of sense. So much code today is hardwired >>>for 32 bit ints that going fully 64 by default would cause a lot of code to >>>fail. By keeping the int at 32 bits, most semi-properly written code will still >>>compile and work. >> >>Problem is all ints are _not_ 32 bits. That was my point. Declare an int on a >>Cray. Or on an alpha... > > >I know. The Cray etc. people complained about that back in the late 80's when >the original ANSI / ISO C standard was being done. > >The C standard people patiently explained the situation to them. That their >charter was limited to "codifying existing practice" (Their words.) That they >only had limited authority to invent or drastically change. > >That's why it waited until the C99 standard. > >And there is absolutely nothing that can be done about plain 'int'. It pretty >much is defined as the machine word. Whatever that happens to be. Yes. But on an "opteron" what would you call a "word" when the processor is in 64 bit mode? That is quite an aggravation... > >But, the standard does allow for some flexibility. Hence, it's possible for a >version of C to have 32 bit ints even on a 64 bit system. And to default to either signed or unsigned for chars, etc. This is less a "standard" than a "guideline" which is really poor... > >And for portability the large number of 32 bit programs that might not be 64 bit >safe, it does make sense. > >Not necessairly the best choice, but it does make sense. > >(In fact, I remember reading articles back in the days when people were moving >from 16 to 32 bits. People were complaining about the difficulties of moving >from 16 to 32 bits. And the Cray people spoke up made similar comments about 32 >bit unix programs being ported to the Cray.) > >The only time it causes problems is if the program author does very stupid >things, like violating cardnial rules of pointers and integers being the same >size. > >That's such a cardnial rule that no programmer today should violate it. But >some do. > >That was a painful lesson we learned the hard way back then. But since then, >most programmers have forgotten about it and are having to relearn it when >moving to 64 bits. > >The reality is that you should never ever expect a pointer to be any particular >size or value. Always use ptrdiff_t, and so on. > >The reality is that if the C compiler author wants to, a pointer could be 96 >bits or more. The compiler author may decide to throw in some extra boundary >info. Or maybe the pointer include extra info such as a page table entry. Or >whatever. > >A properly written C program will never notice what size a pointer is. And the >size of the integer will only be relevant to the amount of regular computational >data it needs to hold. > >In which case, a 64 bit compiler with a 32 bit int can make some sense. > >(Again, not necessarily the best choice. But it can help make unsafe int >behavior less likely to fail. A lot of programs today depend on 32 bit >rollovers, etc.)
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.