Anonymous | Login | 2024-12-12 18:09 UTC |
Main | My View | View Issues | Change Log | Docs |
Viewing Issue Simple Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||
ID | Category | Severity | Type | Date Submitted | Last Update | ||
0000374 | [1003.1(2008)/Issue 7] System Interfaces | Objection | Omission | 2011-02-03 17:12 | 2024-06-11 08:53 | ||
Reporter | eblake | View Status | public | ||||
Assigned To | ajosey | ||||||
Priority | normal | Resolution | Accepted As Marked | ||||
Status | Closed | ||||||
Name | Eric Blake | ||||||
Organization | Red Hat | ||||||
User Reference | ebb.malloc | ||||||
Section | malloc | ||||||
Page Number | 1268 | ||||||
Line Number | 41715 | ||||||
Interp Status | --- | ||||||
Final Accepted Text | Note: 0004507 | ||||||
Summary | 0000374: malloc(0) and realloc(p,0) must not change errno on success | ||||||
Description |
Since the standard explicitly allows malloc(0) and realloc(p,0) to return either NULL or a pointer, an application that wishes to know whether a return of NULL is the result of an implementation that does not allocate (successful) or an implementation that tries to allocate but had no memory (errno == ENOMEM). However, the standard is also explicit that errno cannot be inspected upon success unless documented, and that no function can reset errno to 0. The standard also allows malloc to fail for reasons unrelated to ENOMEM (although this is unlikely to happen). Requiring errno to remain unchanged when a pointer is returned may invalidate existing implementations, so this proposal limits the wording to just the case of a 0-size allocation request. |
||||||
Desired Action |
At line 21395 [XSH calloc DESCRIPTION], change: If the size of the space requested is 0, the behavior is implementation-defined: the value returned shall be either a null pointer or a unique pointer. to: If the size of the space requested is 0, the behavior is implementation-defined: either no allocation attempt is made, <CX>errno shall be unchanged</CX>, and NULL is returned; or an allocation attempt is made which results in a valid pointer if successful and in a NULL return <CX>and a valid errno</CX> if it fails. <CX>Since a return of NULL for a size of 0 may indicate either success or failure, an application wishing to determine which of the two implementations is in use should set errno to 0, then call calloc( ), then check errno.</CX> At line 21410 [XSH calloc RATIONALE], change "None" to: Note that the value of errno is undefined if a pointer is returned; it is only required to be unchanged or valid when NULL is returned. At line 41713 [XSH malloc DESCRIPTION], change: If the size of the space requested is 0, the behavior is implementation-defined: the value returned shall be either a null pointer or a unique pointer. to: If the size of the space requested is 0, the behavior is implementation-defined: either no allocation attempt is made, <CX>errno shall be unchanged</CX>, and NULL is returned; or an allocation attempt is made which results in a valid pointer if successful and in a NULL return <CX>and a valid errno</CX> if it fails. <CX>Since a return of NULL for a size of 0 may indicate either success or failure, an application wishing to determine which of the two implementations is in use should set errno to 0, then call malloc( ), then check errno.</CX> At line 41729 [XSH malloc RATIONALE], change "None" to: Note that the value of errno is undefined if a pointer is returned; it is only required to be unchanged or valid when NULL is returned. At line 56036 [XSH realloc DESCRIPTION], change: If ptr is a null pointer, realloc( ) shall be equivalent to malloc( ) for the specified size. to: If ptr is a null pointer, realloc( ) shall be equivalent to malloc( ) for the specified size. In particular, if the size argument is 0, the behavior is implementation-defined: either no allocation attempt is made, <CX>errno shall be unchanged</CX>, and NULL is returned; or an allocation attempt is made which results in a valid pointer if successful and in a NULL return <CX>and a valid errno</CX> if it fails. <CX>Since a return of NULL for a null pointer and size of 0 may indicate either success or failure, an application wishing to determine which of the two implementations is in use should set errno to 0, then call realloc( ), then check errno.</CX> At line 56058 [XSH realloc RATIONALE], change "None" to: Note that the value of errno is undefined if a pointer is returned; it is only required to be unchanged or valid when NULL is returned. |
||||||
Tags | c99, issue8 | ||||||
Attached Files | |||||||
|
Relationships | |||||||||||||||||||||||||
|
Notes | |
(0000664) eblake (manager) 2011-02-03 17:25 |
Concerns were raised during the 3 Feb 2011 conference about line 56034 of realloc; is realloc(ptr, 0) allowed to return a non-NULL value, and therefore, should a NULL return when ptr is freed also need special treatment for whether errno is unchanged on success. This will require feedback from the C committee. |
(0000708) nick (manager) 2011-03-17 12:30 edited on: 2011-03-17 16:09 |
This was considered during the WG14 meeting in London. On Feb 20, 2011, at 1:48 AM, DAGwyn@aol.com wrote: > In a message dated 2/19/2011 7:45:08 P.M. Eastern Standard Time, > msebor@gmail.com writes: > > 1) there are implementations that do not behave according > > to the C99 requirement and return NULL after deallocating > > the space, and > > 2) the POSIX standard specifically permits such implementations > > 3) there likely are programs that rely on the behavior of such > > implementations. > > Declaring such implementations non-conforming and expecting them > > to change may not be feasible because doing so would introduce > > memory leaks into programs that rely on their behavior. > > Such programs already are not portable without memory leaks, > since on a C99-conforming platform space is not deallocated > when NULL is returned from realloc. If they need to cope with > both C99-conforming and non-conforming implementations as > described in (1), they cannot rely on the deallocation anyway; > change: > // old code which leaks using C99-conforming implementations: > if ((newp = realloc(p, newsize)) == NULL) > if (newsize > 0) > ... // still have previous data, recovery method A > else > ... // non-conforming realloc discarded previous data, > // recovery method B > else { > p = newp; > size = newsize; > } > to: > // new code which doesn't leak regardless of implementation: > if (newsize == 0) { > p = NULL; > size = 0; > } else if ((newp = realloc(p, newsize)) == NULL) > ... // still have previous data, recovery method A > else { > p = newp; > size = newsize; > } > Notice that recovery method B, which is likely to be quite > awkward since the current data has been lost, is no longer > necessary using the second approach. It is likely that the vast > majority of programs using realloc already use something like > the second approach, which avoids realloc(,0) altogether and > which requires less and simpler recovery coding. > > There are already several things wrong with the current POSIX > specification for realloc, as I noted in a previous message. It > should be changed to not contradict the C standard, the simplest > method being to use the C standard's wording except not to say > anything special about the case of size 0. That would remove > permission for implementations to gratuitously report failure to > allocate when space is in fact available. Then the only time that > reasonably-coded programs that had assumed the non-C99 > behavior (1) could leak memory would be when in fact memory > wasn't available, in which case most programs probably adopt a > "recovery" scheme that doesn't continue execution for much > longer, and the leak will evaporate when the program terminates. > > The C committee considered three possibilities: 1. Do nothing and accept the fact that some C99 implementations may not be able to conform to the requirements of the C99 standard in this regard for compatibility reasons. 2. Change C to more closely align with the POSIX requirements so as to make the existing implementatins conforming. This resolution is being sought by the POSIX group and is also preferred by the implementers of the affected implementations. 3. Change both the C and POSIX standards to require realloc() to always attempt to allocate space even for zero-size requests. This would simplify the specification and, at least in theory, also make it easier to write portable programs. This option would require the support of the implementers of the affected implementations. Without such support this option becomes equivalent to option 1 above. The outcome of this discussion is that if realloc returns NULL, it has failed, and the original memory has not been freed. The POSIX words came from C90, and these were changed for C99. POSIX failed to pick up the change See N872 item 19c. Unfortunately this breaks several existing implementations. However, those implementer present (Sun/Oracle, Apple, IBM, HP) all agreed that they were prepared to change their implementations. POSIX Change requested by C99: Page 1754 line 56030 Change: The realloc() function shall change the size of the memory object pointed to by ptr to the size specified by size. The contents of the object shall remain unchanged up to the lesser of the new and old sizes. If the new size of the memory object would require movement of the object, the space for the previous instantiation of the object is freed. If the new size is larger, the contents of the newly allocated portion of the object are unspecified. If size is 0 and ptr is not a null pointer, the object pointed to is freed. to The realloc() function shall deallocate the old object pointed to by ptr and return a pointer to a new object that has the size specified by size. The contents of the new object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values. Page 1754 line 56046 change Upon successful completion with a size not equal to 0, realloc() shall return a pointer to the (possibly moved) allocated space. to Upon successful completion, realloc() shall return a pointer to the (possibly moved) allocated space. At line 56047-8 change: If size is 0, either a null pointer or a unique pointer that can be successfully passed to free() shall be returned. to If size is 0, either: * a null pointer shall be returned <CX>and errno set to EINVAL</CX>, or * unique pointer that can be successfully passed to free() shall be returned, and the memory object pointed to by ptr shall be freed. Add after line 56049: If realloc() returns NULL, the memory referenced by ptr is not changed. Add after 56052: The realloc() function may fail if: EINVAL size is 0 and the implementation does not support 0 sized allocations. NOTE: Since the text at the top of realloc() states: The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2008 defers to the ISO C standard. I am not sure we have the wiggle room to do anything but DEFECT situation. |
(0000722) eblake (manager) 2011-03-24 16:41 |
The issue of leaving errno unchanged on successful allocation is only appropriate for Issue 8; and this bug should not be resolved until after 0000400 regarding the conflict between C99 and POSIX on realloc behavior has been fixed first in TC1. |
(0000737) eblake (manager) 2011-04-07 20:45 |
There are at least three existing realloc behaviors when NULL is returned; the differences only occur for a size of 0 (for non-zero size, all three implementations set errno to ENOMEM when returning NULL, even though that is not required by C99). AIX: realloc(NULL,0) always returns NULL, errno is EINVAL realloc(ptr,0) always returns NULL, ptr freed, errno is EINVAL BSD: realloc(NULL,0) only gives NULL on alloc failure, errno is ENOMEM realloc(ptr,0) only gives NULL on alloc failure, ptr unchanged, errno is ENOMEM glibc:realloc(NULL,0) only gives NULL on alloc failure, errno is ENOMEM realloc(ptr,0) always returns NULL, ptr freed, errno unchanged During the 7 Apr 2011 teleconference, the idea was reiterated that the WG14 intentions were to require BSD behavior, although the wording in C99 has a loophole in implementation-defined behavior that still appears to permit AIX and glibc behaviors. The C1x draft carries the same wording loophole, so the planned course of action is to raise a defect against C1x once it completes standardization, where the outcome of that defect will either be that C1x tightens the wording to eliminate the loophole or relaxes the wording to align with existing practice. Therefore, the behavior of errno in Issue 8 should be deferred until after any C1x defect has been resolved. |
(0001001) nick (manager) 2011-11-03 15:22 |
This was further discussed at the Washington DC meeting of WG14, and C defect report 400 has been accepted. This will not be resolved for at least another 2 meetings - i.e. at least one year. This bug should remain open in the meantime. |
(0001130) nick (manager) 2012-02-16 16:13 |
See Note: 0001129 |
(0002221) geoffclare (manager) 2014-04-10 15:57 |
This was discussed in the 10th April teleconference. We plan to accept these changes in spirit, but since there is overlap with several other bugs, we will wait until after TC2 has been merged into Issue 7 in order to have a clean starting point for the detailed edits. |
(0002222) eblake (manager) 2014-04-10 15:59 |
http://open-std.org/JTC1/SC22/WG14/www/docs/dr_400.htm [^] |
(0004507) geoffclare (manager) 2019-08-02 11:18 |
We need to decide how to handle the overlap between this bug and the work to align Issue 8 with C17. A major rewrite of the realloc() DESCRIPTION and RETURN VALUE sections is needed to align with C17. This will mean most of the changes requested in Note: 0000708 are taken care of by that. The only thing left for this bug to do is to address any changes to CX functionality that we want to make. The original request to leave errno unchanged when a memory allocation function is called with size zero and a null pointer is returned because the implementation did not attempt an allocation appears to conflict with C17, which says (7.22.3 para 1; emphasis added): If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned to indicate an error, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object. So if we want applications to be able to distinguish between implementations that attempt allocation and those that don't, we will need to specify two different non-zero errno values -- Note: 0000708 already suggests using EINVAL for this for realloc() and this seems like an appropriate way to handle it in all the functions. Note also that C17 makes calling realloc() with size 0 an obsolescent feature. I suggest that we should resolve this bug first and then the C17 alignment changes can incorporate the resolution into the rewritten realloc() DESCRIPTION and RETURN VALUE sections. Proposed changes (page and line numbers are for the 2018 edition) ... On page 637 line 22010 section calloc(), change: Upon successful completion with both nelem and elsize non-zero, calloc() shall return a pointer to the allocated space. If either nelem or elsize is 0, then either: to: Upon successful completion, calloc() shall return a pointer to the allocated space; if either nelem or elsize is 0, the application shall ensure that the pointer is not used to access an object. On page 637 line 22019 section calloc(), add: The calloc() function may fail if: On page 1295 line 43152 section malloc(), change: Upon successful completion with size not equal to 0, malloc() shall return a pointer to the allocated space. If size is 0, then either: to: Upon successful completion, malloc() shall return a pointer to the allocated space; if size is 0, the application shall ensure that the pointer is not used to access an object. On page 1295 line 43161 section malloc(), add: The malloc() function may fail if: On page 1788 line 57886 section realloc(), change: A null pointer shall be returned [CX]and, if ptr is not a null pointer, errno shall be set to an implementation-defined value[/CX]. to: A null pointer shall be returned [CX]and, if ptr is not a null pointer, errno shall be set to [EINVAL][/CX]. On page 1788 line 57895 section realloc(), add: The realloc() function may fail if: |
(0004510) Florian Weimer (reporter) 2019-08-07 12:10 |
The C17 change to realloc looks like an editorial mistake. I brought this very issue to the WG14 reflector in May 2018. I was told that the intent was to make a wide range of existing implementation behavior conforming to the standard, and not to require new changes to implementation for maintaining conformance. (In general, C17 is supposed to contain editorial changes only.) glibc will not change realloc for (perceived) C17 conformance. glibc and GCC continue to support zero-sized objects as an extension to the standard. |
(0004517) geoffclare (manager) 2019-08-08 08:31 |
Re: Note: 0004510 It was a deliberate decision by WG14, not any kind of accident or editorial mistake. Their decision is stated in Note: 0000708 (also repeated in bug 0000400 which is where the current POSIX requirement comes from), in particular: "The outcome of this discussion is that if realloc returns NULL, it has failed, and the original memory has not been freed." and "Unfortunately this breaks several existing implementations. However, those implementer present (Sun/Oracle, Apple, IBM, HP) all agreed that they were prepared to change their implementations." As regards C17 containing editorial changes only, according to Note: 0000708 WG14 believed that this change in requirement happened between C90 and C99 (and "POSIX failed to pick up the change"), in which case the later addition of "to indicate an error" can be seen as an editorial clarification. |
(0005445) geoffclare (manager) 2021-08-16 11:09 |
When applying this bug I noticed that the resolution was missing CX shading on the new EINVAL errors and I included this shading. I also worded the realloc() EINVAL slightly differently so that it can apply to reallocarray() as well: "The requested allocation size is 0 and ..." |
Issue History | |||
Date Modified | Username | Field | Change |
2011-02-03 17:12 | eblake | New Issue | |
2011-02-03 17:12 | eblake | Status | New => Under Review |
2011-02-03 17:12 | eblake | Assigned To | => ajosey |
2011-02-03 17:12 | eblake | Name | => Eric Blake |
2011-02-03 17:12 | eblake | Organization | => Red Hat |
2011-02-03 17:12 | eblake | User Reference | => ebb.malloc |
2011-02-03 17:12 | eblake | Section | => malloc |
2011-02-03 17:12 | eblake | Page Number | => 1268 |
2011-02-03 17:12 | eblake | Line Number | => 41715 |
2011-02-03 17:12 | eblake | Interp Status | => --- |
2011-02-03 17:15 | nick | Tag Attached: c99 | |
2011-02-03 17:23 | eblake | Desired Action Updated | |
2011-02-03 17:25 | eblake | Note Added: 0000664 | |
2011-03-17 12:30 | nick | Note Added: 0000708 | |
2011-03-17 12:31 | nick | Note Added: 0000709 | |
2011-03-17 16:07 | nick | Note Deleted: 0000709 | |
2011-03-17 16:09 | nick | Note Edited: 0000708 | |
2011-03-24 16:31 | eblake | Tag Attached: issue8 | |
2011-03-24 16:38 | eblake | Relationship added | child of 0000400 |
2011-03-24 16:41 | eblake | Note Added: 0000722 | |
2011-04-07 20:45 | eblake | Note Added: 0000737 | |
2011-11-03 15:22 | nick | Note Added: 0001001 | |
2012-02-16 16:13 | nick | Note Added: 0001130 | |
2012-02-16 17:15 | nick | Relationship added | related to 0000526 |
2013-05-09 15:57 | eblake | Relationship added | child of 0000688 |
2013-05-09 16:23 | eblake | Relationship deleted | child of 0000688 |
2013-05-09 16:23 | eblake | Relationship added | related to 0000688 |
2014-04-10 15:57 | geoffclare | Note Added: 0002221 | |
2014-04-10 15:59 | eblake | Note Added: 0002222 | |
2019-08-02 11:18 | geoffclare | Note Added: 0004507 | |
2019-08-07 12:10 | Florian Weimer | Note Added: 0004510 | |
2019-08-07 12:11 | Florian Weimer | Issue Monitored: Florian Weimer | |
2019-08-07 21:01 | eblake | Relationship added | related to 0001218 |
2019-08-08 08:31 | geoffclare | Note Added: 0004517 | |
2021-08-12 15:44 | geoffclare | Final Accepted Text | => Note: 0004507 |
2021-08-12 15:44 | geoffclare | Status | Under Review => Resolved |
2021-08-12 15:44 | geoffclare | Resolution | Open => Accepted As Marked |
2021-08-16 11:09 | geoffclare | Note Added: 0005445 | |
2021-08-16 11:09 | geoffclare | Status | Resolved => Applied |
2024-06-11 08:53 | agadmin | Status | Applied => Closed |
Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group |