Live data from Hacker News

Stop Memsetting Structures

anmolsarma.in

111–120 of 277 posts

Re: Stop Memsetting Structures

#111

Because it’s 2019! It really irritates me when people give arguments like this. I seriously don't care what year it is, I care that the code I write works. A lot of projects still use C89 because they want the widest portability. C99 isn't very new, but especially in the embedded and other niche industries, C89 (often with some extensions) is all you get. That said, "= { 0 };" is almost always usable instead of a mem…

#include struct abc { int a; int b; int c; }; int main() { struct abc b = {2}; printf("a b c = %d %d %d\n ", b.a, b.b, b.c); return 0; } % c99 test.c % a.out a b c = 2 0 0

https://stackoverflow.com/questions/10828294/c-and-c-partial...

> The C and C++ standards guarantee that even if an integer array is located on automatic storage and if there are fewer initializers in a brace-enclosed list then the uninitialized elements must be initialized to 0.

It does work for zero-initialization.

Re: Stop Memsetting Structures

#112
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.

Are you accepting bug reports for such issues in tarsnap? :)

Re: Stop Memsetting Structures

#113
post #19
post #10

Earlier quoted context omitted.

No, but the follow up article is called Stop Memcpying Structures. And the follow up to that Stop Memcmping Structures. :)

You're probably not serious, but why waste time and complexity copying structure elements into a buffer (which likely needs to be memset/bzero'd!), if you can just directly use the struct, all consistent with the standard? C is not a very high-level language. Apart from where undefined behavior is called out, you can and should assume how data is represented on a low level. It was made for writing operating systems a…

I'm joking because endless flame wars have already been spent debating this issue. But I realize not everyone has heard them yet, so let's strap on the football shoes and bring out the horse carcass one more time!

There are platforms on which NULL, integer 0 and floating point 0 is not the same. Hence memsetting won't do the right thing. On modern platforms they are, but still, you don't want to get the Standard C Weenies on your back - they're even more annoying than the Rust Evangelism Strike Force. You don't want demons coming out of your nose, do you? :)

They do have a point, though. Suppose you are handling a struct you thought were memsetted but was not (your stupid team mate used those damn initializers!), then when serializing it you will get undefined bytes in the stream, possibly triggering hash values to mismatch causing mysterious rebuilds and other stuff.

Wrt to field accesses, yes those can overwrite padding bytes. Suppose a is an 8 bit char field, but padded to 4 bytes. Then "foo->a = 22" could be translated to "MOV [RSP+16], EAX" which overwrites the 3 padding bytes with undefined values. The solution, as you mention, is to use packed structs but in those field accesses are much less efficient.

Bottom line: code whichever way you want. :) Me, I like to live in the fast lane from time to time and those memset/cpy/cmp functions are sooo handy. :)

Re: Stop Memsetting Structures

#114
post #72

Earlier quoted context omitted.

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.

That is what stdint is for.

Re: Stop Memsetting Structures

#115
post #86
post #77

Earlier quoted context omitted.

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().

If you are processing data from the network, any uninitialized read gets attacked. My experience is padding (both inside a struct, and outside - array alignment for instance) gets attacked. The only safe option is to initialize everything . I say this having spent more than a decade working on software that is always being attacked.

You shouldn't be sending structs over the network, since their specific layout depends on the compiler (and version). At least make them packed if you're gonna do undefined behavior...

But you should just do it the right way and have a wrapper that deals with endianness differences and such:

    struct S my_struct;
    // ...
    push_int64(&output_stream, &my_struct.value1);
    push_string(&output_stream, my_struct.value2);
    push_int32(&output_stream, &my_struct.value3);
And on the receiving side:

    struct S my_struct;
    next_int64(&input_stream, &my_struct.value1);
    next_string(&input_stream, my_struct.value2, sizeof(my_struct.value2));
    next_int32(&input_stream, &my_struct.value3);

Re: Stop Memsetting Structures

#116

Because it’s 2019! It really irritates me when people give arguments like this. I seriously don't care what year it is, I care that the code I write works. A lot of projects still use C89 because they want the widest portability. C99 isn't very new, but especially in the embedded and other niche industries, C89 (often with some extensions) is all you get. That said, "= { 0 };" is almost always usable instead of a mem…

Actually, I had some code that passed null to free(), and it segfaulted on some old version of Red Hat. (Not RHEL, Red Hat.)

Re: Stop Memsetting Structures

#118
post #12
post #2

Does that also zero the padding that may exist between elements of the structure (or at its end)? Because if not, not memset'ing will open you up to all kinds of info leaks, especially if you plan to send that struct over the network (or to another process, or from kernel to userspace...). EDIT: Actually I have to apologize, because I’m not certain what the C standard says about whether the padding bytes can change w…

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.

Serialization is a non-trivial problem. Especially when dealing with different OS, network stacks, and architectures. protobuf alleviates this quite a bit.

Re: Stop Memsetting Structures

#119
post #5

Earlier quoted context omitted.

Same. But also, I feel like most of The Force's efforts are directed at C++. I could be wrong.

C++ programmers need to be converted. C programmers just need sympathy.

We don't really need sympathy, we get paid a lot and can afford to drown our sorrows.

Re: Stop Memsetting Structures

#120
post #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.

[deleted]
Post reply on HN