Hacker News new | ask | show | jobs
by sillysaurus 4803 days ago
but there is still no guarantee it will work on another architecture, another compiler, or even another version of the same compiler.

My point is that it is guaranteed to work. A memory barrier guarantees that all memory operations before the barrier take effect before any operations after the barrier.

I think this whole exchange is fascinating because it illustrates two completely different philosophies to hacking. Both are equally valid. I tend to prefer yours because it tends to result in shorter programs. Yet this is just a programmer convention. The machines do not care.

Yet there are some instances where my philosophy -- understanding which rules may be safely ignored -- has paid off. For example, if your invalid program were in a closed-source library which I was forced to interface with, then the program can't simply be fixed. In that case, a memory barrier would probably be the cleanest workaround.

It's an unfortunate fact that this type of situation -- broken third-party code that can't be fixed and can't be replaced -- is quite common in the field. It seems like it's an important skill for an engineer to know how to handle such situations.

EDIT: By the way, Scrybe Music looks really cool!

1 comments

It isn't guaranteed to work even with the memory barrier, because the undefined behavior is not merely an ordering problem. The problem is that merely accessing the object through the wrong kind of pointer breaks the rules and gives the compiler a license to do anything.

There is a time and place to break the rules, but it is a calculated risk. It can only be considered "safe" if you make assumptions about your environment (platform, toolchain, etc). You're vulnerable if any of those assumptions change. The things people considered "safe" 10 years ago aren't "safe" any more. But the people who followed the rules never have to change their approach.

For what it's worth, a cheaper barrier in this case (if you were going to take that route) is just a compiler barrier like __asm__ __volatile__ (""); (see: http://en.wikipedia.org/wiki/Memory_barrier#Out-of-order_exe...). There's no need to emit an actual CPU barrier.

Thanks about Scribe; it's a labour of love.

I think that your original suggestion - use memcpy is a better solution then volatile.

It looks like the following code would work:

  #include <stdio.h>
  #include <stdint.h>

  void f(volatile uint32_t *x, volatile uint16_t *y) {
    *x = 5;
    printf("%d\n", *y);
  }

  int main() {
    volatile uint32_t x = 10;
    f(&x, (volatile uint16_t*)&x);
  }
And the compiler is guarantied () to issue store op on x = 5 and consecutively load op on y, but the code is looking pretty ugly.

() assuming no alignment problems