Live data from Hacker News

Stop Memsetting Structures

anmolsarma.in

11–20 of 277 posts

Re: Stop Memsetting Structures

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

You are right in theory, but I have yet to come upon a compiler that will use something other than zero for null.

Re: Stop Memsetting Structures

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

Re: Stop Memsetting Structures

#14
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…

Nope it doesn't:

  //GCC:  -O0
  //MSVC: /Od
  #include 
  #include 
  struct S { unsigned char x; int y; };
  int f(int f) { S a; memset(&a, f, sizeof(a)); unsigned char y[2]; memcpy(&y, &a, sizeof(y)); return y[1]; }
  int g() { S a = { 1, 2 }; unsigned char y[2]; memcpy(&y, &a, sizeof(y)); return y[1]; }
  int main(int argc, char *argv[]) { f(0xDD); printf("%#x\n", g()); f(0xFF); printf("%#x\n", g()); }
It definitely seems like the author didn't realize this fact, or I'd have expected it to be addressed in the article.

Re: Stop Memsetting Structures

#17
post #10
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…

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

Did you mean this as a joke? I can't find a follow-up article (this one was written today).

Re: Stop Memsetting Structures

#18
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 there any remaining architectures where NULL is not zero?

The examples listed here are all historical:

http://c-faq.com/null/machexamp.html

Re: Stop Memsetting Structures

#19
post #10
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…

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 and their kernels after all, where interfacing in a bit-accurate way is common.

Re: Stop Memsetting Structures

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

That will never happen on current or future platforms, and is not a big concern. Or perhaps it'd be better to say that if it ever does happen on a future platform, then a few memset calls are going to be the least of your problems when porting legacy C code to that platform.

However, what has bitten me is memsetting structures that I later turn into full-fledged classes in C++. Oops, there went the VMT.

Designated initializers are very nice, as is the ability (in C++) to provide initial-value assignments that run before the constructor.

Post reply on HN