eklhad@ihnet.UUCP (K. A. Dahlke) (09/07/84)
I once had to malloc() a 3-dimensional table. The code was not proprietary, so here is a fragment. mktbl(){ unsigned short (*freq)[ASIZE][ASIZE]; /* malloc a 3-dimensional table of triple frequencies */ freq = (unsigned short ***) malloc(sizeof(unsigned short)*ASIZE*ASIZE*ASIZE); for(i=0;i<ASIZE*ASIZE*ASIZE;++i) freq[0][0][i]=0; ... ++freq[c1][c2][c3]; ... } When I asked a structured programmer how to solve this malloc problem, the answer was immediate and predictable. "put the array in a structure." struct FOO { unsigned short freq[ASIZE][ASIZE][ASIZE]; } *foo; mktbl(){ /* malloc a 3-dimensional table of triple frequencies */ foo = (struct FOO*) malloc(sizeof(unsigned short)*ASIZE*ASIZE*ASIZE); for(i=0;i<ASIZE*ASIZE*ASIZE;++i) foo->freq[0][0][i]=0; ... ++(foo->freq[c1][c2][c3]); ... } The foo-> stuff is annoying to type, but the structures are simpler to understand, and more portable. -- Karl Dahlke ihnp4!ihnet!eklhad
gary@cirl.UUCP (Gary Girzon) (09/03/85)
I would appreciate some help on the following problem. When using malloc() in C ( runing 4.2 bsd ), I cannot allocate more than roughly 4 megabytes. This seems to be limited by our core size. I would like to know whether this limit can be extended to handle virtual memory on the VAX. Also, any information on how the C compiler deals with virtual memory (if at all) would be appreciated. Gary Girzon UUCP: ihnp4!think!cirl!gary
anton@ucbvax.ARPA (Jeff Anton) (09/05/85)
In article <203@cirl.UUCP> gary@cirl.UUCP (Gary Girzon) writes: >I would appreciate some help on the following problem. When using >malloc() in C ( runing 4.2 bsd ), I cannot allocate more than roughly >4 megabytes. This seems to be limited by our core size. I would >like to know whether this limit can be extended to handle virtual >memory on the VAX. Also, any information on how the C compiler deals with >virtual memory (if at all) would be appreciated. The C compiler does not bother with VMem knowledge except for its own use. You are probably encountering a limit imposed by malloc. I'd suggest you try useing sbrk(2). I recently needed a 6 Mbytes for raster plotting and malloc complained but sbrk worked fine. I don't suggest running jobs that exceed system core size, but sometimes we don't have any way around the matter. You might also try out the 'limit' command in csh. Check out sbrk(2), setrusage(2), and the 'obsolete' vadvise(2). (vadvise is hidden in 4.2 for use by lisp, and some CAD tools, and maybe apl; it might be named Ovadvise) -- C knows no bounds. Jeff Anton U.C.Berkeley Ingres Group ucbvax!anton anton@BERKELEY.EDU
chris@umcp-cs.UUCP (Chris Torek) (09/06/85)
The 4.2 malloc rounds each request up to the nearest power of two (sounds space inefficient [and is], but very time efficient; see Korn's paper in Proceedings Winter '85 Usenix). Since as distributed 4.2 has a per-process VM limit of 6M, you cannot allocate more than 4M with malloc. (Of course if you raise the VM limits you can get as much space as you like, provided you have lots of paging space.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland
jon@CIT-VAX.ARPA (Jonathan P. Leech) (09/07/85)
> From: Chris Torek > ... Since as distributed 4.2 has a per-process VM limit of 6M, you > cannot allocate more than 4M with malloc. I don't understand how this works. Suppose I allocate two blocks, one 4M (2^22 bytes) and one 2M (2^21). These are both powers of two, and I get 6M total. Or does malloc round it up by a factor of two if you are unlucky enough to request a power of two (not counting overhead in the free list, of course)? -- Jon Leech (jon@cit-vax.arpa) __@/
chris%umcp-cs.uucp@BRL.ARPA (Chris Torek) (09/08/85)
> From: jon@cit-vax (Jonathan P. Leech) >> From: Chris Torek >> ... Since as distributed 4.2 has a per-process VM limit of 6M, you >> cannot allocate more than 4M with malloc. > I don't understand how this works. Suppose I allocate two blocks, > one 4M (2^22 bytes) and one 2M (2^21). These are both powers of > two, and I get 6M total. Or does malloc round it up by a factor > of two if you are unlucky enough to request a power of two . . . . Sorry, I was not specific enough. You can allocate one 4M chunk and one 2M chunk; you cannot allocate one 6M chunk. The size you hand to malloc has (in our C library at any rate) 4 added to it, then the result is brought up to the nearest power of two. So if you give it ((1 << 22) - 4) you will get a 4M chunk; one more byte and malloc will require an 8M chunk. (If you compile malloc with range checking the overhead grows to 12 bytes.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland
jpl@allegra.UUCP (John P. Linderman) (09/10/85)
> The size you hand to malloc has (in our C library at any rate) 4 > added to it, then the result is brought up to the nearest power of > two. So if you give it ((1 << 22) - 4) you will get a 4M chunk; > one more byte and malloc will require an 8M chunk. > -- > In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251) Chris is right (as usual) about the 4.2 malloc being about 50% efficient when allocating blocks whose size is a power of 2, (like the buffers that stdio will allocate). Another ``gotcha'' to beware of is that space, once allocated, is never broken into smaller pieces. For example, if I allocate a 4 meg temporary workspace, free it, then allocate a 2 meg area, malloc will not reuse the freed space, it will try for a new area, and, thanks to the aforementioned quirks, it will fail with the standard 6 meg per-process limit. Dunno if this is fixed under 4.3. One can hope, but I wouldn't bet the farm. John P. Linderman Space Cadet allegra!jpl
chris@umcp-cs.UUCP (Chris Torek) (09/11/85)
> ... Another ``gotcha'' to beware of is that space, once allocated, > is never broken into smaller pieces. [...] Dunno if this is fixed > under 4.3. > > John P. Linderman Space Cadet allegra!jpl I doubt it will be; it has not yet been done. It might create yet another ``gotcha'', however, as coalescing smaller blocks is fairly tricky. By the way, I quote from my own version of the CalTech malloc which I use in my Emacs: /* If there are no blocks of the appropriate size, go get some */ /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ if (nextf[nunits] == NULL) morecore (nunits); I put that comment in when I rewrote most of the code; the RCS logs say that was 84/06/29---more than a year ago. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland
kwh@bentley.UUCP (KW Heuer) (05/14/86)
In article <866@ttrdc.UUCP> ttrdc!levy (Dan Levy) writes: >Y'know--while I'm thinking about it, why IS malloc() set up to return a >(char *) pointer at all, if that IS inviting a potential (or at least to >lint's little mind) pointer alignment problem? Since malloc() is supposed >to return a maximally aligned pointer, seems to me that it should have >been set up to return a (double *). Yes, yes, before flames of misunder- >standing start, I _KNOW_ that the convention for malloc() is to return >a (char *) and that it returns a maximally aligned pointer just the same >because of the way it has been written. It just seems that the methodology >was back-a**wards, that at least returning a (double *) would indicate an >implicit promise to the user (and to lint-like checking) that the return >value WAS maximally aligned. The only problem I could see with this kind >of scheme is that some systems might not support double. But that could >be gotten around by #defining a malloc_t type that would represent the >maximally aligned data type of the machine at hand. This is what I started to mention once before, and picked up a lot of "no, you don't understand how it works" messages (sigh). I saw the need for a "ALIGN *" datatype, and was hoping "void *" would be it. (Nope, just a useless synonym for "char *"). The idea would be that, just as it's always legal to cast any pointer into a "char *", it would be legal to cast *from* "ALIGN *" to any pointer. Then lint would shut up about malloc()! Also, having malloc() return a real "ALIGN *" would be convenient for word- addressible machines where "char *" requires extra bits. Btw, if I really want to reduce the signal/noise ratio in lint, I use #if lint extern char *cmalloc(); extern int *imalloc(); extern struct foo *fmalloc(); ... #else extern char *malloc(); #define cmalloc(n) ((char *)malloc((n)*sizeof(char)) #define imalloc(n) ((int *)malloc((n)*sizeof(int)) #define fmalloc(n) ((struct foo *)malloc((n)*sizeof(struct foo)) ... #endif Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
jon@cit-vax.Caltech.Edu (Jonathan P. Leech) (05/14/86)
Summary: Expires: Sender: Followup-To: Distribution: Organization : California Institute of Technology Keywords: In article <815@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes: > >This is what I started to mention once before, and picked up a lot of "no, >you don't understand how it works" messages (sigh). I saw the need for a >"ALIGN *" datatype, and was hoping "void *" would be it. (Nope, just a >useless synonym for "char *"). The idea would be that, just as it's always >legal to cast any pointer into a "char *", it would be legal to cast *from* >"ALIGN *" to any pointer. Then lint would shut up about malloc()! > I don't think 'void *' is useless. What do you do on a machine where it's NOT 'always legal to cast any pointer into a "char *"'? I find 'void *' most wonderful and useful in C++. -- Jon Leech (jon@csvax.caltech.edu || ...seismo!cit-vax!jon) Caltech Computer Science Graphics Group __@/
guy@sun.uucp (Guy Harris) (05/14/86)
> I saw the need for a "ALIGN *" datatype, and was hoping "void *" would > be it. (Nope, just a useless synonym for "char *"). The idea would > be that, just as it's always legal to cast any pointer into a "char *", > it would be legal to cast *from* "ALIGN *" to any pointer. Then lint > would shut up about malloc()! No, you just don't understand how it works. From the August 11, 1985 C standard draft: C.2.2.3 Pointers A pointer to "void" may be converted to a pointer to an object of any type. A pointer to an object of any type may be converted to a pointer to "void" or to a pointer to an object of less strict alignment and back again without change. Nowhere is it implied that "void *" is a synonym for "char *". "lint" should not give any complaints about conversions between pointers of other types and pointers to "void" (this isn't stated in the C draft, but then again it's not a description of "lint", it's a language standard). As such, it is not a synonym for "char *", since "lint" should (and does) complain about conversions between "char *" and other pointers. As the C draft clearly states, it is legal to cast *from* "void *" to any pointer; as such, if "malloc" is declared to return "void *", "lint" will shut up about it. No, the language does not *guarantee* that a "void *" is properly aligned, but there's no way for it to do so anyway. Big deal. The language couldn't *guarantee* that an "ALIGN *" is properly aligned either - if you wrote "malloc" in C (as all UNIX implementations I know of are written), you would just have to trust that the implementation delivers a maximally-aligned pointer. As such, "ALIGN *" is just a useless synonym for "void *". > Also, having malloc() return a real "ALIGN *" would be convenient for word- > addressible machines where "char *" requires extra bits. Maybe, but I'm not sure the added convenience of having "malloc" be able to return a value of a type requiring fewer bits is sufficient to justify adding another type to the language. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.arpa
ark@alice.UucP (Andrew Koenig) (05/15/86)
> I don't think 'void *' is useless. What do you do on a machine > where it's NOT 'always legal to cast any pointer into a "char *"'? You don't implement C on it.
kwh@bentley.UUCP (KW Heuer) (05/16/86)
In article <479@cit-vax.Caltech.Edu> cit-vax!jon writes: > I don't think 'void *' is useless. What do you do on a machine >where it's NOT 'always legal to cast any pointer into a "char *"'? You get a compiler that works. The proposed property of "void *" is already guaranteed for "char *". (Sorry, no K&R handy, can't quote it.) Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
levy@ttrdc.UUCP (Daniel R. Levy) (05/19/86)
In article <5462@alice.uUCp>, ark@alice.UucP (Andrew Koenig) writes: >> I don't think 'void *' is useless. What do you do on a machine >> where it's NOT 'always legal to cast any pointer into a "char *"'? > >You don't implement C on it. Why not? If a "char *" per se (the machine's idea of a byte address) doesn't contain sufficient information to reconstruct another type of address from it, you could always have the compiler generate code to carry around enough extra information with the C pointers to allow reconstruction of pointers to larger data types. Can anyone name such a machine which wouldn't be amenable to this? I'm not talking about machines that are hostile to unbridled pointers like the Burroughs beasts (no hardware memory protection). I'm talking about machines whose byte and word addressing schemes have no relationship whatsoever. -- ------------------------------- Disclaimer: The views contained herein are | dan levy | yvel nad | my own and are not at all those of my em- | an engihacker @ | ployer or the administrator of any computer | at&t computer systems division | upon which I may hack. | skokie, illinois | -------------------------------- Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa, vax135}!ttrdc!levy
kwh@bentley.UUCP (KW Heuer) (05/19/86)
In article <3674@sun.uucp> sun!guy writes: [bentley!kwh writes:] >> I saw the need for a "ALIGN *" datatype, and was hoping "void *" would >> be it. (Nope, just a useless synonym for "char *"). The idea would >> be that, just as it's always legal to cast any pointer into a "char *", >> it would be legal to cast *from* "ALIGN *" to any pointer. Then lint >> would shut up about malloc()! > >No, you just don't understand how it works. From the August 11, 1985 C >standard draft: > > C.2.2.3 Pointers > > A pointer to "void" may be converted to a pointer to an > object of any type. A pointer to an object of any type may be > converted to a pointer to "void" or to a pointer to an object > of less strict alignment and back again without change. > >Nowhere is it implied that "void *" is a synonym for "char *". Since sizeof(char) == 1 (I believe that's now a guaranteed rule rather than merely "true in all known implementations", right?), it has the least strict alignment. Thus your last quoted sentence implies that "char *" can also hold a pointer of any type, and restore it unchanged. And to even attempt to restore it means that "char *" must meet the first property as well. So, although not necessarily synonyms, they do have the same properties, except that "char *" conversions usually require a cast to be acceptable. >No, the language does not *guarantee* that a "void *" is properly aligned, >but there's no way for it to do so anyway. Big deal. The language couldn't >*guarantee* that an "ALIGN *" is properly aligned either... What I had in mind was that "ALIGN *" would be a synonym for "int *" or whatever happens to be the most restrictive pointer type. The "guarantee" would be as good as the "guarantee" on an "int *". >> Also, having malloc() return a real "ALIGN *" would be convenient for word- >> addressible machines where "char *" requires extra bits. > >Maybe, but I'm not sure the added convenience of having "malloc" be able to >return a value of a type requiring fewer bits is sufficient to justify >adding another type to the language. Well, what *is* the justification for adding "void *" to the language? To allow people to shove pointers around without casts? (Shudder!) To make lint shut up about malloc()? Or just to distinguish "generic pointers" from pointers that can be dereferenced? (Could be done with a typedef. So could "void", but they put it in anyway.) I do not strongly object to the addition of "void *", but I am worried about it "hiding" errors. (I'm one of those purists who thinks that programmers *should* use casts to change types.) Also, it's a misnomer; it has nothing to do with "void". Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
rbutterworth@watmath.UUCP (Ray Butterworth) (05/22/86)
> Well, what *is* the justification for adding "void *" to the language? To > allow people to shove pointers around without casts? (Shudder!) To make > lint shut up about malloc()? Or just to distinguish "generic pointers" from > pointers that can be dereferenced? (Could be done with a typedef. So could > "void", but they put it in anyway.) > > I do not strongly object to the addition of "void *", but I am worried about > its "hiding" errors. (I'm one of those purists who thinks that programmers > *should* use casts to change types.) Also, it's a misnomer; it has nothing > to do with "void". When I first heard of (void*), I thought it was a wonderful idea. malloc() and realloc() would return this type and it would be guaranteed to be properly aligned and assignable to any other type of pointer without complaint. This much turned out to be true. I also thought that casting anything into a (void*) would be a big no-no. Lint, and maybe even the compiler, would issue loud warnings every time one tried to do this. This wouldn't matter since normal programs would never need to do it, and the warnings would only be generated when malloc() and realloc() were compiled. Unfortunately this turned out to be false. For some perverse reason that I have never been able to understand, X3J11 decided that any pointer could be converted to (void*) without complaint. There was no need for this additional usage since the standard also guarantees that any pointer may be correctly cast to (char*). It adds nothing useful and makes it much easier to code undetectible errors. (Lint complains too much about your code? Don't worry, just change all the pointers to void* and it will shut up. (I assume you already "#define CALL (void*)" and put CALL in front of all your function calls so that you don't have to check any error statuses.) Perhaps lint should have an option which redirects all output to /dev/null?)
chris@umcp-cs.UUCP (Chris Torek) (05/24/86)
The real reason for `void *', which everyone seems to be missing,
is that it provides a generic pointer type.
Of course, if you need such a thing, you can usually get away with
union all_possible_ptrs {
char *ifchar;
unsigned char *ifuchar;
short *ifshort;
unsigned short *ifushort;
int *ifint;
unsigned int *ifunit;
long *iflong;
unsigned long *ifulong;
float *iffloat;
double *ifdouble;
};
but it is conceivable that this might be insufficent on a
machine with special structure pointers. On such a machine,
this union might be (say) 30 bits wide, whereas a generic
pointer might be 34 bits. Thus `void *'.
Besides, do you really *want* to use such a union?
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP: seismo!umcp-cs!chris
CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
guy@sun.UUCP (05/24/86)
> I also thought that casting anything into a (void*) would be a big > no-no. Lint, and maybe even the compiler, would issue loud warnings > every time one tried to do this. The key word here is "warnings". The X3J11 standard doesn't say what constructs may not give warnings; it merely states what is and isn't legal C. As long as the compiler produces code for it, X3J11 doesn't care how many complaints it puts out. Maybe C should be stricter about types (I think so), but it's too late for that. > This wouldn't matter since normal programs would never need to do it... Well, err, umm, "void *" is also useful for declaring objects used by several different modules, where each client of the object's implementation wants to store some private data in the object, and you can't get away with statically restricting the class of modules using this object. Dennis Ritchie's "streams" article in the BSTJ gives an example of this. A "queue" has pointers to "put" and "service" procedures, and a "void *" which provides private storage for those procedures. Replacing that "void *" with a "struct tty *", or a union of similar structures, would be ridiculous. Yes, you can't rely on the type system to check correctness. (Maybe something like Goedel's Incompleteness Theorem applies, where any type system strong enough that all programs written using it are "correct" is incomplete, in that there exist interesting and meaningful programs which cannot be written within this type system?) > For some perverse reason that I have never been able to understand, > X3J11 decided that any pointer could be converted to (void*) without > complaint. No, they just decided that it could be so converted in a legal C program. Appendix E.3 gives a list of warnings which many implementations might give; the situations listed are all legal C, but may not be desirable C. > (Lint complains too much about your code? Don't worry, just change > all the pointers to void* and it will shut up. (I assume you already > "#define CALL (void*)" and put CALL in front of all your function > calls so that you don't have to check any error statuses.) Perhaps > lint should have an option which redirects all output to /dev/null?) If you're worried about programmers trying to spoof "lint" you'd better find some way of preventing them from hiding all dubious code inside "#ifdef lint". C is not guaranteed to work in an environment where you have to ride herd on programmers. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.arpa
bright@dataioDataio.UUCP (Walter Bright) (05/27/86)
In article <3754@sun.uucp> guy@sun.uucp (Guy Harris) writes: >> I also thought that casting anything into a (void*) would be a big >> no-no. Lint, and maybe even the compiler, would issue loud warnings >> every time one tried to do this. >> For some perverse reason that I have never been able to understand, >> X3J11 decided that any pointer could be converted to (void*) without >> complaint. Ah, but if you have a function prototype such as: extern void free(void *); and then try to free a pointer to a struct, you are implicitly casting the struct pointer to a void *. Generating an error on this would make void * fairly useless.
guy@sun.UUCP (05/28/86)
> In article <3754@sun.uucp> guy@sun.uucp (Guy Harris) writes: > >> I also thought that casting anything into a (void*) would be a big > >> no-no. ... Guy Harris wrote nothing of the sort. Karl W. Z. Heuer wrote that. The "In article..." crap is put there by *some* versions of "postnews", but not all. (The version we run here doesn't put it there, for example.) It is, therefore, an unreliable indicator, and should probably be deleted before sending out articles. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.arpa
rbutterworth@watmath.UUCP (Ray Butterworth) (05/29/86)
> Ah, but if you have a function prototype such as: > extern void free(void *); > and then try to free a pointer to a struct, you are implicitly casting > the struct pointer to a void *. Generating an error on this would > make void * fairly useless. But if I were king, free() wouldn't take a (void*). Almost the only place (void*) would be used is by malloc(). There is a need for two special types of generic pointers: one which is guaranteed to be aligned and can be cast into any other pointer, and one which has no such guarantee and can have any other pointer cast into it. (void*) clearly fits the former. (char*) almost fits the latter (perhaps a new (pointer) type should have been introduced). X3J11 defeated the niceness of all this by extending their definition of (void*) to fit both requirements. I really don't understand why they would do such a thing. It gains nothing and loses a lot.
kwh@bentley.UUCP (KW Heuer) (05/30/86)
In article <3788@sun.uucp> guy@sun.UUCP (Guy Harris) writes: >> In article <3754@sun.uucp> guy@sun.uucp (Guy Harris) writes: >> >> I also thought that casting anything into a (void*) would be a big >> >> no-no. ... > >Guy Harris wrote nothing of the sort. Karl W. Z. Heuer wrote that. Wrong squared. It was watmath!rbutterworth who wrote it. Karl W. Z. Heuer (ihnp4!bentley!kwh), the Walking Lint
ron@brl-sem.ARPA (Ron Natalie <ron>) (06/01/86)
In article <113@watmath.UUCP>, rbutterworth@watmath.UUCP (Ray Butterworth) writes: > There is a need for two special types of generic pointers: one which > is guaranteed to be aligned and can be cast into any other pointer, and > one which has no such guarantee and can have any other pointer cast > into it. (void*) clearly fits the former. (char*) almost fits the > latter (perhaps a new (pointer) type should have been introduced). > X3J11 defeated the niceness of all this by extending their definition > of (void*) to fit both requirements. I really don't understand why > they would do such a thing. It gains nothing and loses a lot. Eh? "void *" is a pointer that is big enough to hold any other pointer. It makes no attempt at alignment. Nowhere in C is there any guarantees on alignment. You assign an unaligned char into an int pointer on some machines it will work, some it won't be aligned right, and some will generate bizarre pointers as a result. It is a feature of MALLOC that it never puts anything into that void* it returns that isn't aligned, but that is extremely implentation dependant. -Ron