1

I have a structure which contains an array elements like this

    #define SIZE 20
    typedef struct
    {
        int currentindex;
        int array[SIZE];
    } tempstruct;

    int main()
    {
        int fd;
        tempstruct *ptr = NULL;
        fd = shm_open("/TESTPROG", O_RDWR | O_CREAT, 0666);
        ptr = mmap(0,sizeof(tempstruct),PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        /* 
        So in case SIZE is not compile time constant but another int then I do this
        ptr = mmap(0,sizeof(tempstruct),PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        ptr.array = (int*)malloc(sizeof(int)*SIZE);
    */
        return 0;
    }

As you can see that I use mmap to allocate instance of this tempstruct on shared memory area but now due to some changes I want to dynamically allocate array element of tempstruct structure as SIZE will not be compile time constant. So will above program be still valid ? like can I allocate array on heap and then mmap'ed it to shared memory so will array in another process points to same heap area ? I guess no so please suggest some better ways ?

Thanks

barak manos
  • 29,648
  • 10
  • 62
  • 114
user3494614
  • 603
  • 1
  • 7
  • 20
  • Just call `mmap`. It's just like `malloc`, except that the memory comes from the shared memory block instead of the heap. But you can use it as a pointer to a structure in the same way. – Barmar Apr 17 '14 at 11:47
  • I know that but earlier array was allocated by mmap only now array is just a pointer and I have to allocate it using another malloc so there are two memory allocation and I am not sure wheather second memory allocation will be visible in another process? – user3494614 Apr 17 '14 at 11:50
  • Memory allocations from `malloc` are not visible to another process, only memory allocations from `mmap`. – Barmar Apr 17 '14 at 11:53
  • The above program becomes in un-compilable as soon as you do this: `ptr.array = ...;`. Arrays are not assignable, and if this is supposed to be memory mapped between processes, changing that member to a pointer and storing a `malloc` result will wreak havoc on any other process addressing through that pointer. In short, no, it won't work. If you *want* to map both the `currentIndex` and an var-len array you can do so using a [*flexible array member*](http://stackoverflow.com/questions/14643406/whats-the-need-of-array-with-zero-elements/14643530#14643530), but you better know what you're doing. – WhozCraig Apr 17 '14 at 11:58

2 Answers2

2

Here is one way to solve this:

typedef struct
{
    int currentindex;
    int array[0];
}
tempstruct;

int main()
{
    ...
    int totalSize = sizeof(tempstruct) + sizeof(int) * numOfElements;
    ptr = mmap(0, totalSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    ...
}

Please note that you will not be able to properly utilize an array of tempstruct instances.

barak manos
  • 29,648
  • 10
  • 62
  • 114
  • A good solution, but worth noting that [zero-length arrays](http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html) are a GCC extension and not ISO C. However, if the array length will always be at least 1, `array[1]` will work just as well. – Clifford Apr 19 '14 at 21:27
  • 1
    You can actually leave off the array size altogether, declaring the array as `int array[];`. This works as long as `array` is the last member of the struct, and it does not lie about the array being of a fixed size. – cmaster - reinstate monica Apr 19 '14 at 22:01
0

The malloc'ed memory block would belong to the process that performed the malloc, and the other process would not access the same memory (and may cause an exception).

Use a zero length array, or an array of length 1 if you are not using GCC or enforcing ISO C, and simply create the mmap block sizeof tempstruct + size of array. Because C does not perform bounds checking on arrays, you can access the memory outside teh structure as if it were an array at the end of the structure.

This technique will only work if array is the last member of the struct, and the struct is not nested in some other struct with following members. As tempstruct is an anonymous struct, you cannot do that in any case.

Clifford
  • 88,407
  • 13
  • 85
  • 165