Compiler optimization, streaming security?

I have a question regarding optimizations that the compiler could potentially do.

The code below will speak for itself (this is an example):

typedef struct test { short i; } s_test; int function1(char *bin) { s_test foo; lock(gmutex); foo.i = *(int*)bin * 8; unlock(gmutex); sleep(5); // // Here anything can happen to *bin in another thread // an inline example here could be: *(volatile int *)bin = 42; // int b = foo.i + sizeof(char*); return (b > 1000); } 

Can the compiler replace last lines with

 return ((*(int*)bin * 8 + sizeof(char*)) > 1000); 

This is not like using -O2 or -O3 with gcc 4.4, but could it be the case with other compilers and other compilation flags?

+7
source share
3 answers

I do not think that the compiler will do such an optimization.

 unlock(gmutex) 

it is a function, the compiler cannot assume that the value specified in bin will be changed in the unlock function or not.

for example, maybe a bit comes from the globe. Therefore, optimization for bin cannot cross over a function call.

+5
source

Your example is unnecessarily complicated because you read bin different type than declared. The rules for aliases are quite complex, char even special, I would not comment on this.

Suppose your declaration would be int* bin (and therefore you would not need to overlay a pointer), the compiler would not have the right to reorder expressions in function calls, they form the so-called sequence points. The *bin value before and after the unlock call may differ, so it should load the value after the call.

Edit: as noted by slartibartfast, for this argument it is important that unlock be (or contain) a function call and is not just a macro that allows the compiler to execute the sequence of operations.

+4
source

As I said in the direct answer: your mutex does not protect anything IMHO. The char array that * bin is placed into can be modified during int-access, so depending on your computer, you won’t even get a consistent representation in the memory that you wanted to access. Let's get back to your question: the compiler does not convert the source code into the sequence that you intended, but it can very well produce a machine language, which essentially behaves the way your source code does. If it is capable of checking function locks, unlocking and hibernating (which appear to be macros anyway), and can infer that there is no side effect for the memory locations involved, and there is no definite implementation definition for calls, for example. sleep (), which will display temporary ("cached", although the standard does not use this term) values ​​are invalid, then it has the right to produce a sequence of commands, such as the one you gave. C (before C99) is essentially single-threaded, and the compiler can use any optimization strategy that it wants, while the code behaves β€œas it were,” it will work on an ideal hypothetical machine C. The sequence points that Jens mentioned do not affect correct under single-thread conditions: the compiler can hold foo in the register during the whole function or it can even alias foo.i with the memory address pointed to by * bin, so this code (at least I think it will not demonstrate this behavior is for most wa compilers).

+1
source

All Articles