Live data from Hacker News

Stop Memsetting Structures

anmolsarma.in

71–80 of 277 posts

Re: Stop Memsetting Structures

#71

Interestingly enough, Clang (but not GCC) appears to embed memset for you despite the code using initializers: https://godbolt.org/z/khJQLV The author of the article should file a bug report. After all, if they wanted to memset, they'd just do it themselves.

The compiler knows the representation of NULL on the targeted platform and if it is safe to use memset. It is perfectly valid for the compiler to make this transformation if the platform represents NULL as zero.

Re: Stop Memsetting Structures

#72
post #12

Earlier quoted context omitted.

Sending structures that include padding or that you don’t know the exact layout of over the network is another thing you shouldn’t do, period. Code doing that may break with a compiler change or a compilation flag change on one end of the connection, even if you can guarantee both ends use the same CPU.

Changing compiler or flags won't change structs, unless you do something crazy. If it did, you couldn't link C libraries compiled with one compiler with programs compiled on another. You can't be sure you can send such structures to different OSes or CPUs however.

It depends upon the architecture and compiler. One C compiler for the MC68000 might have int as 16 bits (since externally, the MC68000 had a 16-bit external bus) but another one have ints as 32 bits (since the MC68000 can handle 32-bits internally). This was more of an issue during the 80s and 90s when you had more commercial C compiler available than today.

Re: Stop Memsetting Structures

#73
post #70

Earlier quoted context omitted.

So if you're zeroing out a struct like so struct S {size_t a, void *p;}; foo = (struct S) {0}; Does the standard require the compiler to set any pointers to NULL, or will everything be implicitly zeroed leaving pointers possibly improperly initialized to NULL?

The pointers are required to be initialized to NULL in your example (even if the representation is different from memset of zero).

[deleted]

Re: Stop Memsetting Structures

#74

Am I the only one who finds this int yes=1; setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)) ; much cleaner than this setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &(int) {1}, sizeof(int)); ?

But it's C99, so you can do:

    setsockopt(listener, SOL_SOCKET, SO_REUSERADDR, &(int) {true}, sizeof(int));
I think this makes the intent clearer.

Re: Stop Memsetting Structures

#75
post #33
post #30

Because of c spec idiocy it isn’t event sufficient to use memset anymore, you need to use memset_s. But “stop memsetting” is clearly nonsense if you care about security.

Surely you only need memset_s if you're doing this for security reasons, as if memset is optimized away it's because the compiler can prove the observable semantics are the same.

Nope, memset will often be “optimized” such that padding is not zeroed. It’s not because the compiler sees that padding isn’t observed, it’s because reading from padding is undefined. Because reading from padding is undefined the write (also undefined) by definition has no observable side effects.

Memset_s is the only way to guarantee that padding is actually zeroed, well memset or bzero_s obviously.

It’s critically important for people to understand that if the C spec says doing X is undefined, then current compiler writers interpret this as allowing them to do anything they want, even when it clearly introduces security vulnerabilities.

Re: Stop Memsetting Structures

#76
post #70

Earlier quoted context omitted.

So if you're zeroing out a struct like so struct S {size_t a, void *p;}; foo = (struct S) {0}; Does the standard require the compiler to set any pointers to NULL, or will everything be implicitly zeroed leaving pointers possibly improperly initialized to NULL?

The pointers are required to be initialized to NULL in your example (even if the representation is different from memset of zero).

[deleted]

Re: Stop Memsetting Structures

#77
post #75
post #33

Earlier quoted context omitted.

Surely you only need memset_s if you're doing this for security reasons, as if memset is optimized away it's because the compiler can prove the observable semantics are the same.

Nope, memset will often be “optimized” such that padding is not zeroed. It’s not because the compiler sees that padding isn’t observed, it’s because reading from padding is undefined. Because reading from padding is undefined the write (also undefined) by definition has no observable side effects. Memset_s is the only way to guarantee that padding is actually zeroed, well memset or bzero_s obviously. It’s critically…

Right, but zeroing padding only matters for security reasons. If your memset isn't being done for security reasons, then memset() is better than memset_s().

Re: Stop Memsetting Structures

#78
post #7

Another reason to not memset structures: In the code struct foo { void * bar; } baz; ... memset(&baz, 0, sizeof(struct foo)); assert(baz.bar == NULL); it's possible for the assertion to fail, since NULL it not guaranteed to be represented in memory by a zero bytes.

> it's possible for the assertion to fail, since NULL it not guaranteed to be represented in memory by a zero bytes. Technically correct (which is of course the best kind of correct) but you'd be hard pressed to find a system in 2019 where NULL != (void*)0. The most recent machines with non-zero NULL in the C FAQ entry on the matter ( http://c-faq.com/null/machexamp.html ) date back to the mid '90s.

Technically no such system exists ;)

But talking about the actual bit representation. A zero value as a special pointer with the magic property of being invalid is a convention for C on x86, right?

I assume it has to do with it's fast to check the zero-flag in EFLAGS register when doing checks for null pointers.

Re: Stop Memsetting Structures

#79
post #44

Am I the only one who finds this int yes=1; setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)) ; much cleaner than this setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &(int) {1}, sizeof(int)); ?

No, you are not the only one. The author of that code is trying to make it explicit -- "yes, I want to allow reuse of local addressses". Some will prefer this, some won't. I personally like the use of the variable, though I think it's not worth getting all bent out of shape about it one way or another. But I guess we all have our pet peeves, and I know I'm guilty of getting all bent out of shape about things that ult…

Code is read many times more than it is written. If someone scrutinizes code for clear intent, I don’t think that should be considered a “pet peeve” or some quirk to be explained away.

Re: Stop Memsetting Structures

#80
post #71

Interestingly enough, Clang (but not GCC) appears to embed memset for you despite the code using initializers: https://godbolt.org/z/khJQLV The author of the article should file a bug report. After all, if they wanted to memset, they'd just do it themselves.

The compiler knows the representation of NULL on the targeted platform and if it is safe to use memset. It is perfectly valid for the compiler to make this transformation if the platform represents NULL as zero.

My post is sarcasm, I just find it humorous that one's efforts to eliminate explicit memset doesn't stop the compiler from going one step backwards and embedding it just the same. If you replace the initialization with memset, it still generates identical code for both Clang and GCC.
Post reply on HN