Вот очень интересный пример... 1-й - это то, что уже показывалось раньше с alloca(), а 2-й - это подобное, переписанное с VLA ... оба примера примерно приведены к похожему виду:Olej писал(а):Я так понимаю (предполагаю), что динамические массивы VLA стандарт C99 вводит вместо плохо стандартизованного (между компиляторами, платформами) вызова alloca(). Что есть почти одно и то же (или совершенно одно и то же?). Только, естественно, нельзя одновременно использовать и один и другой механизм, потому что вместе, не зная друг о друге, они просто разрушат стек.
Код: Выделить всё
#define N 6
void test053( void ) { // alloca() данных в блоке
void *X[ N ];
int i;
void *p = &p; // дно кадра стека
printf( "alloca() в блоке:\n" );
printf( "дно стека = %p\n", p );
for( i = 0; i < N; i ++ ) {
X[ i ] = alloca( sizeof( short ) );
*(short*)X[ i ] = i + 1;
printf( "%p[%03d]->%d%s",
X[ i ], p - (void*)X[ i ], *(short*)X[ i ],
( N / 2 - 1 ) == i % ( N / 2 ) ? "\n" : " ,\t" );
}
}
Код: Выделить всё
void test055( void ) { // динамические массивы (C99)
short *X[ N ];
int i;
void *p = &p; // дно кадра стека
printf( "VLA в блоке:\n" );
printf( "дно стека = %p\n", p );
for( i = 0; i < N; i ++ ) {
short V[ i + 1 ];
V[ 0 ] = i + 1;
X[ i ] = &V[ 0 ];
printf( "%p[%03d]->%d%s",
X[ i ], p - (void*)X[ i ], *X[ i ],
( N / 2 - 1 ) == i % ( N / 2 ) ? "\n" : " ,\t" );
}
}
Но особенно интересно выполнение:
Код: Выделить всё
olej@notebook:~/2014_WORK/AntonG/examples.draft$ ./function 6 7
06 ---------------------------------------
alloca() в блоке:
дно стека = 0xbfe9135c
0xbfe91330[044]->1 , 0xbfe91310[076]->2 , 0xbfe912f0[108]->3
0xbfe912d0[140]->4 , 0xbfe912b0[172]->5 , 0xbfe91290[204]->6
07 ---------------------------------------
VLA в блоке:
дно стека = 0xbfe9135c
0xbfe91334[040]->1 , 0xbfe91334[040]->2 , 0xbfe91334[040]->3
0xbfe91334[040]->4 , 0xbfe91334[040]->5 , 0xbfe91334[040]->6
------------------------------------------
Но!
- массивы, создаваемые alloca() внутри блока for, не уничтожаются при завершении блока (выходе за блок), каждый новый массив размещается по новому адресу, освобождены они будут только по завершению функции в которой выполняются, т.е. при переразметке стекового кадра...
- а точно так же создаваемые массивы VLA (и почти там же лежащие) уничтожаются при достижении конца блока, и каждый новый массив в цикле размещается по тому же адресу, где был и 1-й массив.
Вот вам и разница!