2 ms·
It's portably assuming that you can cast an allocation's pointer to a pointer to unsigned char. It's like assuming you can memset(), since that's effectively w
by cryptonector 5y ago
It's portably assuming that you can cast an allocation's pointer to a pointer to unsigned char. It's like assuming you can memset(), since that's effectively what it's doing. In the absence of memory over-commit, this will have no effect beyond wasting resources. In the presence of over-commit -bounded stacks resemble memory over-commitment!- it will have the effect of committing the memory OR failing in whatever way the machine fails when resources are exhausted. However, in the latter case, and when the machine uses stacks for C function calls, the failure will be defined by the machine rather than undefined (due to memory corruption).
Also, in the absence of stacks, there's no "direction in which the stack grows", and any attempt to determine that direction will yield a nonsensical result, but doing memset() in one direction or the other will also then be equivalent anyways.
EDIT: There is one non-portable thing here: the assumption that machines are more limited than size_t implies. However, that's a distinction without a difference for any 64-bit ABIs or larger because all such machines must be more limited than size_t implies. That there is any failure mode when resources are exhausted is a non-portable assumption is uselessly true. Not being able to assume defined resource exhaustion failure modes would be destructive -- that the C spec does not is irrelevant.
- khrbtxyz 5y agodetermine stack growth direction by having one function call another with a pointer to a local variable in the former and then compare that to a pointer to a local variable in the latter. This is undefined behavior. See n1570.pdf, Annex J page 560, J.2 Undefined behavior Pointers that do not point to the same aggregate or union (nor just beyond the same array object) are compared using relational operators (6.5.8).
- cryptonector 5y agoComparing the uintptr_t cast of two disparate pointers is not undefined behavior. A comparison may not yield a portable result because the integer representation of pointers may not be as plain memory addresses. So such a simplistic stack growth detector may get the wrong answer, but it's not undefined behavior: char stack_grows_up(uintptr_t callers_local) { char my_local = (uintptr_t)&my_local > callers_local; return my_local; } EDIT: Ah, and uintptr_t is an optional type. If the platform doesn't have it (e.g., because it's a segmented memory architecture) then this won't work, so it's not portable, but aside from that it's not undefined behavior, it's just that the computation of stack growth direction may well be wrong.