Код: Выделить всё
[19:25:16] вот сишный код:
[19:25:31] :
int Static[5];
int func(void)
{
int Stack[5];
Static[5] = 0;
Stack [5] = 0;
return 0;
}
[19:25:55] : например я перепишу это на джаву
[19:26:11] : это не вызовет ошибку времени компиляции
[19:26:19] : но это вызовет ошибку времени выполнения
[19:26:38] : я пытаюсь обратиться к пятому элементу массива размерностью 5
[19:26:48] : а элементы в нем: 0 1 2 3 4
[19:27:00] : что будет в С
[19:27:12] : скомпилируется ли это? если да - что будет при работе?
На конкретный прямой вопрос (там их, собственно, 2) краткий ответ будет такой:
- конечно это успешно скомпилируется ...
- а при работе такого кода ... может быть всё, что угодно
- конечно, запись за пределами массива - критическая ошибка, но эта ошибка может быть даже не замечена при выполнении.
А для подробного ответа лучше посмотреть код:
Код: Выделить всё
#include <stdio.h>
#include <stdlib.h>
//#define SIZE 3
//#define SIZE 5
#define SIZE 8
int Static0[ SIZE ] = {}, Static1[ SIZE ] = {}, Static2[ SIZE ] = {};
void show( int arr[], int* base ) {
printf( "%p\t[%c%02d] : ",
&arr[ 0 ],
( &arr[ 0 ] - base < 0 ? '-' : '+' ),
abs( &arr[ 0 ] - base ) );
int i;
for( i = 0; i < SIZE; i++ )
printf( "%d%s", arr[ i ], ( SIZE - 1 != i ? ", " : "\n" ) );
}
void show3( int arr0[], int arr1[], int arr2[] ) {
int *b = &arr0[ 0 ];
show( arr0, b ), show( arr1, b ), show( arr2, b );
printf( "------------------------------------------\n" );
}
int main( int argc, char* argv[] ) {
int Stack0[ SIZE ], Stack1[ SIZE ], Stack2[ SIZE ], i;
show3( Stack0, Stack1, Stack2 );
for( i = 0; i < SIZE; i++ )
Stack0[ i ] = Stack1[ i ] = Stack2[ i ] = 0;
show3( Stack0, Stack1, Stack2 );
Stack1[ SIZE ] = 7;
show3( Stack0, Stack1, Stack2 );
show3( Static0, Static1, Static2 );
Static1[ SIZE ] = 7;
show3( Static0, Static1, Static2 );
Static1[ -25 ] = 7;
return 0;
}
Код: Выделить всё
[Olej@modules Init]$ make init
gcc -Wall init.c -o init
[Olej@modules Init]$ ./init
0x7fff3635d900 [+00] : 194, 0, 0, 0, 4196224, 0, 4195472, 0
0x7fff3635d8e0 [-08] : -1906175640, 48, 0, 0, 1, 0, 4196301, 0
0x7fff3635d8c0 [-16] : -1, 0, 1, 0, -1904148032, 48, -924658088, 32623
------------------------------------------
0x7fff3635d900 [+00] : 0, 0, 0, 0, 0, 0, 0, 0
0x7fff3635d8e0 [-08] : 0, 0, 0, 0, 0, 0, 0, 0
0x7fff3635d8c0 [-16] : 0, 0, 0, 0, 0, 0, 0, 0
------------------------------------------
0x7fff3635d900 [+00] : 7, 0, 0, 0, 0, 0, 0, 0
0x7fff3635d8e0 [-08] : 0, 0, 0, 0, 0, 0, 0, 0
0x7fff3635d8c0 [-16] : 0, 0, 0, 0, 0, 0, 0, 0
------------------------------------------
0x601060 [+00] : 0, 0, 0, 0, 0, 0, 0, 0
0x601080 [+08] : 0, 0, 0, 0, 0, 0, 0, 0
0x6010a0 [+16] : 0, 0, 0, 0, 0, 0, 0, 0
------------------------------------------
0x601060 [+00] : 0, 0, 0, 0, 0, 0, 0, 0
0x601080 [+08] : 0, 0, 0, 0, 0, 0, 0, 0
0x6010a0 [+16] : 7, 0, 0, 0, 0, 0, 0, 0
------------------------------------------
Ошибка сегментирования (core dumped)
- локально объявленные но не инициализированные переменные (массивы с том числе) - инициализированы начально мусором;
- глобально объявленные или статические переменные инициализированы нулевыми значениями (как мы легко увидим, они размещаются в совсем другой секции объектного файла);
- мы пишем (значение 7) за пределами массива №1, но никаких segmentation fault не получаем, мы "попадаем" (портим значения!) либо массива объявленного раньше для локальных переменных, либо позже - для глобальных.
- то же, что для массивов (здесь просто это чаще) может быть и для простых скалярных переменных:
Код: Выделить всё
int x = 2, *p = &x;
*(p + 10 ) = 3; // ;-)
Размещение секций кода можем смотреть по собранному бинарному файлу:
Код: Выделить всё
[Olej@modules Init]$ nm init
000000000060103c B __bss_start
0000000000601040 b completed.6338
0000000000601038 D __data_start
0000000000601038 W data_start
00000000004004c0 t deregister_tm_clones
0000000000400530 t __do_global_dtors_aux
0000000000600e18 t __do_global_dtors_aux_fini_array_entry
0000000000400808 R __dso_handle
0000000000600e28 d _DYNAMIC
000000000060103c D _edata
00000000006010c0 B _end
00000000004007f4 T _fini
0000000000400550 t frame_dummy
0000000000600e10 t __frame_dummy_init_array_entry
00000000004009d0 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000400418 T _init
0000000000600e18 t __init_array_end
0000000000600e10 t __init_array_start
0000000000400800 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
w _Jv_RegisterClasses
00000000004007f0 T __libc_csu_fini
0000000000400780 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
000000000040068f T main
U printf@@GLIBC_2.2.5
U puts@@GLIBC_2.2.5
00000000004004f0 t register_tm_clones
0000000000400580 T show
000000000040062e T show3
0000000000400490 T _start
0000000000601060 B Static0
0000000000601080 B Static1
00000000006010a0 B Static2
0000000000601040 D __TMC_END__