Hum answering this 7 years after opening. Contrary to what has been answered so far there is a hope for the dare devils :).
I came across this need, sharing a global VLA (dyn array, etc...) in a threaded app.
Short story, I need my thread to share a global array, I put on the side the synchro/cache problematics here as I just want to show how to share the VLA, this example can be derivated for other needs (for instance an external VLA, etc...)
Here is the code, followed with annotation explaining why it works.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
int gn, gm, *ga; /* (*2) */
void worker(int tndx, long n, long m, int a[n][m]) /* (*6) */
{ long *np=&n, *mp=&m, i=mp-np, *ap=mp+i; /* (*7) */
*ap=(long)ga;
/* At this oint the worker can elegantly access the global dyn array.
* elegantly mean through a[i][j].
*/
printf("worker %d started\n", tndx);
for(int j=0;j<m;j++)
{ a[tndx][j]+=(tndx*1000); /* (*8) */
}
}
void *init_thread(void *v)
{ int x[1][1], tndx = (int)(long)v; /* (*4) */
printf("thread #%d started\n", tndx);
worker(tndx, (long)gn, (long)gm, x); /* (*5) */
return(0);
}
int main(int ac, char **av)
{ int n=atoi(av[1]), m=atoi(av[2]);
pthread_t tt[n]; /* thread table */ /* (*1) */
int a[n][m]; /* dyn array */ /* (*1) */
gn=n, gm=m, ga=&a[0][0]; /* globals setup shared by workers */ /* (*2) */
for(int i=0, k=0;i<n;i++)for(int j=0;j<m;j++)a[i][j]=k++; /* (*3) */
printf("Init a[][]\n");
for(int i=0, k=0;i<n;i++)for(int j=0;j<m;j++)
printf("a[%d][%d]=%d\n",i,j,a[i][j]);
for(int i=0;i<n;i++)
{ if(pthread_create(&tt[i], NULL, init_thread, (void *)(long)i))
{ exit((printf("pthread_create %d failed\n",i),1));
}
}
printf("Draining threads\n");
for(int i=0;i<n;i++)
{ pthread_join(tt[i],0);
}
printf("Final a[][]\n");
for(int i=0, k=0;i<n;i++)for(int j=0;j<m;j++)
printf("a[%d][%d]=%d\n",i,j,a[i][j]);
pthread_exit(NULL);
}
(*1) Here we declare VLA's, the runstring will dictate the number of threads, along with the size of our 2 dim VLA, n lines (1 per threads) with m values each.
(*2) We declare (en setup) our global VLA, we expose our global n and m (as gn, gm) and our global array as a pointer to the array scalar type (int here), we init it to point to a[0][0].
(*3) we setup values in a[n][m] (consecutives int, 0, 1, 2, ...)
(*4) Each threads are started with the init_thread(), note we declare a dummy array of same type as our a[n][m] VLA, the purpose here is to pass an array that is compliant with our worker() API.
(*5) Our worker require a type long for n, m (the dim) this is explained at (*6), so here we pass the global n and m to our worked, and the dummy array, we don't care about it, the only purpose is to pass an array addr as argument.
(*6) The worked API, we have some args (like tndx) then we have a VLA, denoted by long, n, long m, int a[n][m]. At this point a[][] is x[][] and not usefull.
We used long for n and m on purpose to fix some stack aligment surprise that may occurs, then n, m, and a are glued together, because we take the addr of n and m, thos args that are on register (modern arch) are dumped into the stack in their place holder, i=mp=np take care of defining the stack direction (arg0, arg1, arg2) at this point we are able to access the x[][] base addr and place our global ga in there *ap=(long)ga;
(*8) Now our worked can elegantly access the global (shared) VLA.
Here is a run
VY$ cc -o t2 t2.c -lpthread
VY$ ./t2 3 4
Init a[][]
a[0][0]=0
a[0][1]=1
a[0][2]=2
a[0][3]=3
a[1][0]=4
a[1][1]=5
a[1][2]=6
a[1][3]=7
a[2][0]=8
a[2][1]=9
a[2][2]=10
a[2][3]=11
thread #0 started
worker 0 started
thread #2 started
worker 2 started
thread #1 started
worker 1 started
Draining threads
Final a[][]
a[0][0]=0
a[0][1]=1
a[0][2]=2
a[0][3]=3
a[1][0]=1004
a[1][1]=1005
a[1][2]=1006
a[1][3]=1007
a[2][0]=2008
a[2][1]=2009
a[2][2]=2010
a[2][3]=2011
Each thread has modified its line my adding its ID*1000.
So we definitly can have a VLA defined globaly.
VLA's are cool, save the need for the learner to read about alloca() etc, yet there is a need for global one and as explained at compile time it is not possible, still GCC (libgcc?) should be able to offer an API to 'patch' a VLA base addr at run time.
I now that many will voice against arg addr taking, stack direction hack, etc, yet this is the way many other code works, va_args, alloca, etc... so it may look ugly, but this ugliness could be hidden.
Cheers,
Phi