Search code examples
ccompilationvolatile

How to change the value of a variable without the compiler knowing?


I want to verify the role of volatile by this method. But my inline assembly code doesn't seem to be able to modify the value of i without the compiler knowing. According to the articles I read, I only need to write assembly code like __asm { mov dword ptr [ebp-4], 20h }, I think I write the same as what he did.

actual output:

before = 10
after = 123

expected output:

before = 10
after = 10

Article link: https://www.runoob.com/w3cnote/c-volatile-keyword.html

#include <stdio.h>

int main() {
    int a, b;
    // volatile int i = 10;
    int i = 10;

    a = i;
    printf("before = %d\n", a);

    // Change the value of i in memory without letting the compiler know.
    // I can't run the following statement here, so I wrote one myself
    // mov dword ptr [ebp-4], 20h
    asm("movl $123, -12(%rbp)");

    b = i;
    printf("after = %d\n", b);
}

Solution

  • I want to verify the role of volatile ...

    You can't.

    If a variable is not volatile, the compiler may optimize; it does not need to do this.

    A compiler may always treat any variable as volatile.

    How to change the value of a variable without the compiler knowing?

    Create a second thread writing to the variable.

    Example

    The following example is for Linux (under Windows, you need a different function than pthread_create()):

    #include <stdio.h>
    #include <pthread.h>
    
    int testVar;
    volatile int waitVar;
    
    void * otherThread(void * dummy)
    {
        while(waitVar != 2) { /* Wait */ }
        testVar = 123;
        waitVar = 3;
        return NULL;
    }
    
    int main()
    {
        pthread_t pt;
        waitVar = 1;
        pthread_create(&pt, 0, otherThread, NULL);
        testVar = 10;
        waitVar = 2;
        while(waitVar != 3) { /* Wait */ }
        printf("%d\n", testVar - 10);
        return 0;
    }
    

    If you compile with gcc -O0 -o x x.c -lpthread, the compiler does not optimize and works like all variables are volatile. printf() prints 113.

    If you compile with -O3 instead of -O0, printf() prints 0.

    If you replace int testVar by volatile int testVar, printf() always prints 113 (independent of -O0/-O3).

    (Tested with the GCC 9.4.0 compiler.)