|
jmaida wrote: if MEM_WANTED < 0, malloc and calloc return NULL, an expected result
Not quite. The signature for malloc is
void *malloc(size_t size); Note that the argument for malloc is a size_t which is an unsigned value. Assuming a 32 bit operating system then malloc(-1) is the same as malloc(4294967295) which you would expect to return NULL and set ENOMEM. However, that's not a guarantee. Consider a 32 bit program running in a 64 bit environment with 64GB RAM. The OS may be able to do some VM magic to honor that request.
Keep Calm and Carry On
|
|
|
|
|
Hopes and prayers are not best practices across the world of programming.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Perhaps.
But the programming world, both compilers and users, are 100% humans so one must accept that nothing is perfect.
|
|
|
|
|
agree. I did human factor simulations for a bit and humans are human.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Totally agree. Humans are great at pattern recognition, but can miss the obvious. I play a computer game called hidden object adventure. It is strange how the obvious is so easily missed.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
to jschell
That is a fact.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
If < zero behaves like zero, according to some then my first warning holds true.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
as to the signed aspect. Yes it may not be interpreted that way, but my malloc and calloc wrappers avoid any confusion.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
on the esp32 platform, size_t is signed. it maps to int.
surprised me too, in a bad way, with compiler warnings.
To err is human. Fortune favors the monsters.
|
|
|
|
|
ouch! that hurts.
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|
Weird.
According to the C++ standard (at least it's draft ): "The type size_t is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object".
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|
|
Because the first thing I expect when dealing with C++ is a standards conformant C++ environment.
But you know what's really fun?
Being confronted with the C++ standard by wise-alecks with google.
To err is human. Fortune favors the monsters.
|
|
|
|
|
learned this the other day.
To err is human. Fortune favors the monsters.
|
|
|
|
|
You are again confusing the implementation with the Standard. The compiler on my DeathStation 9000 returns a (different) non-NULL pointer for each malloc(0), and is equally compliant as MSVC or GCC, which return NULL.
The Standard defines the argument to malloc() as size_t, which in its turn is defined as an unsigned type that is the result of the sizeof operator. This implies that any negative value cannot be passed to malloc(); any negative argument shall be converted to an equivalent unsigned value.
Section 7.22.3 of the Standard gives the following possible results for a call to malloc(size):
- size > 0 - either the call succeeds (non-null pointer), or it fails (null pointer, errno set)
- size == 0 - [implementation-defined behaviour] either call succeeds (non-null pointer), or it fails (null pointer, errno set)
- size < 0 - non-compliant with the Standard
When a non-NULL pointer is returned, it points to a memory block of at least size characters. There is no exception of the case of size == 0; the memory block is at least of size 0.
The codewitch reports that at least one compiler defines size_t as an a signed value. This is non-compliant with the Standard, and therefore the compiler is arguably not a C compiler.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Negative memory issue I get. A bogus argument for malloc regardless of the argument type. Yet one more reason for a malloc wrapper.
I do not understand your argument that I am confusing implementation with the standard. I am not.
MSVC and GCC do not return NULL for malloc of zero just like your machine does.
Not returning NULL is the problem.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
jmaida wrote: Not returning NULL is the problem.
No it is not! The standard clearly says that malloc(0) may return a non null value. For some reason, you seem to think this is a problem. It's like arguing that an inch should be exactly 2.5 cm rather than 2.54. No. the standard says that an inch is 2.54 cm, and all your wishing it otherwise will not change anything. Deal with it. Or move on to some other (a)vocation.
Keep Calm and Carry On
|
|
|
|
|
I am dealing with it, k5054. That is my point. I know what the standard says.
I have an issue with that standard.
Why would one want to allocate zero memory? Not logical.
I know there a dozen ways to deal with it.
My wrapper recommendation is just one of them.
Any problem with that?
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Not returning NULL is the problem.
Unless you join the standards committee, propose the change and get it voted in, not returning NULL is NOT a problem. Sure it may be a problem for 'you' but compilers need to follow the standard because that's the only thing you can rely on. You should never rely on behavior that is undefined.
|
|
|
|
|
Understood. Just making a point. Sorry to have been a problem.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Since the result of malloc(wanted) for wanted==0 is undefined (across plattforms)
the natural thing is to test wanted
before calling malloc
"If we don't change direction, we'll end up where we're going"
|
|
|
|
|
megaadam wrote: Since the result of malloc(wanted) for wanted==0 is undefined (across platforms)
When discussing Standards, we must use the correct terms. The C Standard differentiates between Undefined Behaviour and Implementation Defined Behaviour.
Undefined Behaviour means precisely that. The implementation is within its rights to do anything - format your disk, set fire to your cat, or make demons fly out of your nose. Avoid at all costs!
Implementation-Defined Behaviour means that the implementation may choose between a few different implementations listed in the Standard, the choice being documented in those manuals that nobody ever reads ( ). The behaviour of malloc(0) is one of these. One should attempt to avoid these in the interest of writing portable code, but they are sometimes necessary.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
While what you say is technically correct I daresay that if you replace "undefined (across plattforms)" in my statement
With any of:
- implementation defined
- unknown, by programmer [due to unspecified implementation]
- any
you still should check wanted==0 [and avoid the syscall if true], especially if you want your code to be portable.
And I never said "Undefined Behaviour" I said "undefined (across platforms)". Still, from a strict perspective that was a slightly sloppy wording, yes.
"If we don't change direction, we'll end up where we're going"
|
|
|
|
|
We like to create wrappers for most standard APIs. Mostly to make it easier to swap implementations without impacting application code.
Consider a higher level allocation concept where you
MyThing* next = allocMyThing(…);
You could have a static (or dynamic) MyThing that covers the case correctly and cleanly where the malloc(0) case crops up.
Different types will need different implementations to correctly avoid malloc(0).
IF you stick with allowing malloc(0), try some more band aids…
If running in test:
it might be best to assert and crash the program. What condition is trying to malloc(0)? Fix it.
For non-test:
It seems like your wrapper method could check for 0 size and return a (global?) static pointer to a zeroed block of memory.
You would get a safe pointer back, but like other posters have pointed out, you should never really dereference a pointer to nothing. If this is cast to char*, you would have a in effect a zero length string.
If you use a global static, the caller could check against the returned value for an exact pointer match, but again it seems it would be best to never call malloc(0).
If it is new code, avoid the malloc(0) calls.
If this legacy code, good luck!
Edit
If you use the static, your wrapper for free() will need to check for a match and skip the actual call to free().
If you wrap malloc, you need to wrap the inverse API as well!
|
|
|
|
|
All excellent advise. Some which I already follow. Thanks, appreciate it.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Wordle 549 4/6
⬛⬛⬛🟨⬛
⬛⬛🟩⬛🟨
🟩🟩🟩⬛⬛
🟩🟩🟩🟩🟩
Back to normal!
|
|
|
|