gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/04/89)
In article <9132@alice.UUCP> andrew@alice.UUCP (Andrew Hume) writes: >the ONLY justification put forward is some stuff about zero-sized >objects (gwyn admits to being the point of contact). the only >point actually mentioned is devising semantics for zero-sized objects; ... I believe that was in fact the only technical issue involved in the decision to permit malloc(0) to fail for reasons other than running out of memory. There were several X3J11 members who, rightly recognizing that if the standard permitted portable programs to rely on malloc(0) succeeding under normal circumstances it would also have to address the issue of semantics for 0-sized objects, balked at having to cross that threshold. I'm a big fan of 0-sized objects, but I've become convinced that formally recognizing them would have significant impact in several places in the standard. The amount of work to get all the technical points right was considered more than could be justified simply to support the style of malloc() usage you're interested in. Incidentally, our last-minute reworking of the wording about last-plus- one element of arrays, etc. may have provided most of the scaffolding needed to formally support 0-sized objects as well. However, 0-sized objects could not be allowed without explicit full committee action, since they had been explicitly disallowed in previous voting. Some people might make the argument that it is more likely when malloc() is called with a 0 size request that there is a bug in the program than that it is a consistent and sensible thing to be attempting. Certainly it COULD be used for legitimate purposes as Andrew apparently does, but most of the malloc() applications I've seen are already in trouble if they get to the point where they would be malloc(0)ing. Thus I don't think the ANSI-portable malloc() behavior poses a significant problem. #define myalloc(n) malloc((n)?(n):1)
bothner@sevenlayer.cs.wisc.edu (Per Bothner) (07/15/90)
I'm trying to clarify the allowed implementation of malloc(0). I'm hoping the standard permits malloc(0) to actually allocate memory (for each call). (In other words, a implementation is allowed to in essence convert malloc(0) to malloc(small_positive_integer).) This behavior is actually *required* for C++, according to Ellis&Stroustrup: The Annotated C++ Reference Manual, and it would be nice if it were at least *permitted* in C. The question hinges of the meaning of the phrase "unique pointer" below: 4.10.3 Memory management functions The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly freed or reallocated). Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation- defined; the value returned shall be either a null pointer or a unique pointer. The value of a pointer that refers to freed space is indeterminate. One suggested interpretation is that "a unique pointer" means a globally static/fixed address. Another is a "pointer to an object disjoint from any other object." This is seems more reasonable to me. However, the definition of realloc() (4.10.3.4) seems to conflict with the latter interpretation: If SIZE is zero and PTR is not a null pointer, the object it points to is freed. --Per Bothner bothner@cs.wisc.edu Computer Sciences Dept, U. of Wisconsin-Madison
gwyn@smoke.BRL.MIL (Doug Gwyn) (07/24/90)
In article <10830@spool.cs.wisc.edu> bothner@sevenlayer.cs.wisc.edu (Per Bothner) writes: >I'm trying to clarify the allowed implementation of malloc(0). >I'm hoping the standard permits malloc(0) to >actually allocate memory (for each call). (In other words, >a implementation is allowed to in essence convert malloc(0) >to malloc(small_positive_integer).) A conforming implementation may do that, or it may always return a null pointer. If the pointer is non-null, it should point to a storage region having a distinct address from all other object and 0-malloc()ed addresses. >The question hinges of the meaning of the phrase "unique pointer" below: No, the important issue is that there are no 0-sized objects in C, so the program making a malloc(0) call is not strictly conforming, and thus a conforming implementation is free to interpret the malloc(0) request as it sees fit; however, other constraints should be obeyed. The clear intent of the pointer uniqueness requirement is to ensure that equality of valid pointers implies that the same object is pointed to by both pointers. If it were not for this requirement, all malloc(0) requests could be satisfied by returning a constant pointer to some valid library object. As it is, however, a distinct pointer should be handed out for each active malloc(0). Since each allocated block normally has an associated bookkeeping header in front of it, this is easy to accomplish with linked-list allocation schemes. With a "buddy system" allocator special care must be taken to change the size from 0 to some positive value. (I don't recommend "buddy system" allocators anyway.) >However, the definition of realloc() (4.10.3.4) seems >to conflict with the latter interpretation: > If SIZE is zero and PTR is not a null pointer, the object it points > to is freed. It's not a conflict, just a reason to be careful if you want to exploit an implementation's extended malloc(0) support.
dan@oresoft.com (Daniel Elbaum) (07/27/90)
In <13384@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >In article <10830@spool.cs.wisc.edu> bothner@sevenlayer.cs.wisc.edu (Per Bothner) writes: >>I'm trying to clarify the allowed implementation of malloc(0). >A conforming implementation may ... always return a null >pointer. If the pointer is non-null, it should point to a storage region >having a distinct address from all other object and 0-malloc()ed addresses. >>The question hinges of the meaning of the phrase "unique pointer" below: >No, the important issue is that there are no 0-sized objects in C, so >the program making a malloc(0) call is not strictly conforming, and thus >a conforming implementation is free to interpret the malloc(0) request >as it sees fit; however, other constraints should be obeyed. The clear >intent of the pointer uniqueness requirement is to ensure that equality >of valid pointers implies that the same object is pointed to by both >pointers. If it were not for this requirement, all malloc(0) requests >could be satisfied by returning a constant pointer to some valid library >object. How can one zero-sized object be the "same" as another? Since C does not have zero-sized objects, a program must not do anything with that which is pointed to by the return value of malloc(0). If an implementation chooses to return a valid pointer to an object of no particular size, it's still illegal to use that object. The pointer is "unique" insofar as it can only be obtained by a call to malloc or calloc with a zero argument. Is this meaning of "unique" consistent with the wording and intent of 4.10.3? >>However, the definition of realloc() (4.10.3.4) seems >>to conflict with the latter interpretation: >> If SIZE is zero and PTR is not a null pointer, the object it points >> to is freed. >It's not a conflict, just a reason to be careful if you want to exploit >an implementation's extended malloc(0) support. "Freeing" an object appears to mean, according to 4.10.3.2, making that object available to future calls to malloc() and calloc(). If the object is already available in a way that does not conflict with 4.10.3, then the call to free() is permitted to have nil effect. -- Being conservative in most respects and reluctant to transform country and constitution, the coup d'etat typically neither attracts nor needs the fanatic. ({uunet,tektronix,reed,sun!nosun,m2xenix}!oresoft!(dan)@oresoft.com)
gwyn@smoke.BRL.MIL (Doug Gwyn) (07/29/90)
In article <1990Jul26.232216.15093@oresoft.com> dan@oresoft.com (Daniel Elbaum) writes: >Is this meaning of "unique" consistent with the wording and intent of 4.10.3? Unique pointers mean just what I said in my previous message. I don't know why you're concentrating on the (empty) content of the objects; I was discussing pointers to the objects, which is what matters here. I could repeat what I said before, or you could retrieve it and study it until you understand my point.
dan@oresoft.com (Daniel Elbaum) (08/01/90)
In <13441@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: :In article <1990Jul26.232216.15093@oresoft.com> dan@oresoft.com (Daniel Elbaum) writes: :>Is this meaning of "unique" consistent with the wording and intent of 4.10.3? :Unique pointers mean just what I said in my previous message. :I don't know why you're concentrating on the (empty) content of the objects; :I was discussing pointers to the objects, which is what matters here. :I could repeat what I said before, or you could retrieve it and study :it until you understand my point. Your point isn't difficult to understand. But it was stated as an assertion rather than a conclusion. You said The clear intent of the pointer uniqueness requirement is to ensure that equality of valid pointers implies that the same object is pointed to by both pointers. If it were not for this requirement, all malloc(0) requests could be satisfied by returning a constant pointer to some valid library object. I meant to ask what you mean by "the same object." Suppose we have two library routines, malloc1() and malloc2(). Malloc1 conforms to the requirements you mentioned in your previous posting. Malloc2 behaves like the hypothetical routine suggested in Bothner's original article--it always returns the same valid pointer when called with a zero argument, and never returns that pointer when called with a nonzero argument. Now if two valid pointers are obtained from malloc1(0) (with no intervening call to free()), the pointers are known to be distinct. If, on the other hand, two pointers are obtained from malloc2(0), their values are known to be identical. They compare equal, but it's impossible to say that they point to the same object, because what they point to isn't, formally speaking, an object. Leaving aside the issue of ease of implementation, each approach has one major advantage. Malloc1 provides a safe means of obtaining a unique, valid pointer. Malloc2 provides a single value for the pointer-to-zero-sized-object. Either may be useful according to the application. For example, one approach to error handling might take advantage of malloc2's behavior by checking pointers against the "known-zero" pointer at critical spots in a program. In short, the second approach has some merit. How (and why) is it forbidden by the Standard? -- Being conservative in most respects and reluctant to transform country and constitution, the coup d'etat typically neither attracts nor needs the fanatic. ({uunet,tektronix,reed,sun!nosun,m2xenix}!oresoft!(dan)@oresoft.com) -- Being conservative in most respects and reluctant to transform country and constitution, the coup d'etat typically neither attracts nor needs the fanatic. ({uunet,tektronix,reed,sun!nosun,m2xenix}!oresoft!(dan)@oresoft.com)
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/03/90)
In article <1990Jul31.222850.1873@oresoft.com> dan@oresoft.com (Daniel Elbaum) writes: >If, on the other hand, two pointers are obtained from malloc2(0), their >values are known to be identical. They compare equal, but it's impossible >to say that they point to the same object, because what they point to isn't, >formally speaking, an object. It is, if the implementation provides this 0-sized object extension. >In short, the second approach has some merit. How (and why) is it >forbidden by the Standard? A strictly conforming program may not rely on malloc() supporting 0-sized objects at all. If some implementation provides such support as an extension, it should do so in a way that is consistent with the principles used in the standard. In this context, the most important principles are that pointers to distinct objects must not compare equal, and that each invocation of malloc() must allocate an object distinct from all other currently valid objects. I provide this just as guidance for implementors. Technically, such extensions are constrained by the standard only to the extent that they can be interpreted in terms of the basic standard. Since there are no explicit guidelines for 0-sized objects in the standard, some attributes of such objects in an extended implementation are subject to "judgement calls". As Point Of Contact for 0-sized objects, I've heard essentially all of the arguments pro and con each choice, and what I recommend is simply my best judgement concerning the matter. In particular, if programs are to make real use of 0-sized objects, they will benefit greatly if separately-malloc()ed ones do not seem to have equal pointers. Try writing some heavy-duty applications involving this stuff and see what I mean.
bobj@gli.com (Robert Jacobs) (08/06/90)
About using malloc(0) to point to a unique place. What's wrong with using malloc(1) ?? That way malloc(0) would do what is expected. Return a NULL pointer. This just seems too easy, doesn't it?
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/07/90)
In article <1990Aug6.142050.18629@gli.com> bobj@gli.com (Robert Jacobs) writes: >About using malloc(0) to point to a unique place. What's wrong with using >malloc(1) ?? >That way malloc(0) would do what is expected. Return a NULL pointer. >This just seems too easy, doesn't it? Yes, it seems too easy because it is too easy. The issue was that it is not clear what to "expect" malloc(0) to return. The standard was deliberately vague on this point, because X3J11 was fairly evenly divided on the issue, but in much better agreement that it wasn't such an important point that it had to be nailed down in the spec.