// swap_testing.c // Built via (c++ was clang++ 4.0 in my case): // // cc -g -std=c11 -Wpedantic swap_testing.c // -O0 and -O2 also gets the problem. #include // for fork(), sleep(.) #include // for pid_t #include // for wait(.) extern void test_setup(void); // Sets up the memory byte patterns. extern void test_check(void); // Tests the memory byte patterns. extern void partial_test_check(void); // Tests just [0] of each region // (gbl_region and dyn_region). int main(void) { test_setup(); test_check(); // Before fork() [passes] pid_t pid = fork(); int wait_status = 0;; // After fork; before waitsleep/swap-out. if (0==pid) partial_test_check(); // Even the above is sufficient by // itself to prevent failure for // region_size 1u through // 4u*1024u! // But 4u*1024u+1u and above fail // with this access to memory. // The failing test is of // (*dyn_region).array[4096u]. // This test never fails here. if (0 // for bool, true, false #include // for size_t, NULL #include // for malloc(.), free(.) #include // for raise(.), SIGABRT #define region_size (4u*1024u+1u) // Bad dyn_region pattern, parent and child // processes: // 256u, 2u*1024u, 4u*1024u, 8u*1024u, // 9u*1024u, 12u*1024u, 14u*1024u // (but see the partial_test_check() call // notes above). // Works: // 14u*1024u+1u, 15u*1024u, 16u*1024u, // 32u*1024u, 256u*1024u*1024u typedef volatile unsigned char value_type; struct region_struct { value_type array[region_size]; }; typedef struct region_struct region; static region gbl_region; static region * volatile dyn_region = NULL; static value_type value(size_t v) { return (value_type)((v&0xFEu)|0x1u); } // value now avoids the zero value since the failures // are zeros. void test_setup(void) { dyn_region = malloc(sizeof(region)); if (!dyn_region) raise(SIGABRT); for(size_t i=0u; i