0

I'm trying to understand how extern variables work when using dynamic linking and dynamic loading of shared libraries, and whether or not a large codebase that I've inherited could have problems in it. Unfortunately I cannot share code from this codebase, and wish to figure out if there's a specific issue here. I would like to know if a variable that is part of a shared library can be mutated from multiple processes that dynamically loads the shared library.

This is the main.c file.

// main.c
#include <stdio.h>
#include <unistd.h>

#include "foo.h"

int main(void)
{
    while(1){
        printf("Value = %d\n", global);
        foo();
    }
    return 0;
}

This is the foo.c file.

// foo.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int global = 0;

void foo(void)
{
    global = global + 1;
    sleep(1);
}

and this is the foo.h file.

// foo.h
#ifndef foo_h__
#define foo_h__

extern void foo(void);
extern int global;

#endif  // foo_h__

This is the Makefile for compiling this program.

# Makefile

all: main

main:
    gcc -c -Wall -Werror -fpic foo.c
    gcc -shared -o libfoo.dylib foo.o
    gcc -Wall -o test main.c -lfoo -L.

Since the global variable has an extern definition, and since a shared library is created, I was expecting that code would break when run across multiple processes. However, if I open two terminals and run ./test in both of them simultaneously, the counter increments independently and correctly (no common shared memory). I'm glad this is how it works, but I'm curious if there's a way to break this? Reading through these answers [1-2], I thought that the shared libraries memory was loaded just once into the virtual memory space and I was under the assumption that the above code would not work, i.e. when starting the second process the first process would reset back to zero. How do I force this code above to increment the value in the same memory address in different processes? Is this possible at all?

[1] https://stackoverflow.com/a/19374253/5451769

[2] https://softwareengineering.stackexchange.com/a/244666

kdheepak
  • 1,274
  • 11
  • 22
  • Most compilation models distinguish between writable and nonwritable memory. When a shared library is shared between multiple processes, they all share a single copy of the shared library's nonwritable memory (code and constant data), but they each get their own copy of the library's writable data. Needless to say, your variable `global` would be in a writable data segment, and would not be shared. – Steve Summit May 04 '18 at 16:56
  • If you want two processes to share some memory, you can create a shared memory segment with the `shm*` system call(s). – Steve Summit May 04 '18 at 16:58

0 Answers0