ここには、共有メモリにデータを書き込むプログラムfoo.c
があります。volatileキーワードが使用されていても、strncmp()によって共有メモリの読み込みを最適化するのはなぜですか?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
key_t key;
int shmid;
char *mem;
if ((key = ftok("ftok", 0)) == -1) {
perror("ftok");
return 1;
}
if ((shmid = shmget(key, 100, 0600 | IPC_CREAT)) == -1) {
perror("shmget");
return 1;
}
printf("key: 0x%x; shmid: %d\n", key, shmid);
if ((mem = shmat(shmid, NULL, 0)) == (void *) -1) {
perror("shmat");
return 1;
}
sprintf(mem, "hello");
sleep(10);
sprintf(mem, "exit");
return 1;
}
同じ共有メモリからデータを読み取る別のプログラムbar.c
があります。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
key_t key;
int shmid;
volatile char *mem;
if ((key = ftok("ftok", 0)) == -1) {
perror("ftok");
return 1;
}
if ((shmid = shmget(key, sizeof (int), 0400 | IPC_CREAT)) == -1) {
perror("shmget");
return 1;
}
printf("key: 0x%x; shmid: %d\n", key, shmid);
if ((mem = shmat(shmid, NULL, 0)) == (void *) -1) {
perror("shmat");
return 1;
}
printf("looping ...\n");
while (strncmp((char *) mem, "exit", 4) != 0)
;
printf("exiting ...\n");
return 0;
}
私はライタープログラムを最初に1つの端末で実行します。
touch ftok && gcc foo.c -o foo && ./foo
ライタープログラムが実行されている間、私は別のターミナルでリーダープログラムを実行します。
gcc -O1 bar.c -o bar && ./bar
リーダプログラムは無限ループに入ります。それはそれは一度読まれた後mem
でデータを修正することができるループでは何も見ないので、オプティマイザは
while (1)
;
に次のコード
while (strncmp((char *) mem, "exit", 4) != 0)
;
を最適化しているように見えます。
しかし、mem
をvolatile
と正確に宣言しました。コンパイラがそれを最適化しないようにします。
volatile char *mem;
なぜコンパイラはまだmem
の読み込みを最適化しますか?
ところで、私は解決策を見つけました。機能するソリューションは
while (mem[0] != 'e' || mem[1] != 'x' || mem[2] != 'i' || mem[3] != 't')
;
に
while (strncmp((char *) mem, "exit", 4) != 0)
;
を修正するために、なぜそれがコンパイラがstrncmp((char *) mem, "exit", 4) != 0
を離れて最適化していることですが、char *mem
は、両方のケースでvolatile
であると宣言されていても離れてmem[0] != 'e' || mem[1] != 'x' || mem[2] != 'i' || mem[3] != 't'
最適化しませんか?