// pseudo process
// User 또는 Application 또는 OS 가 프로그램을 실행합니다
os.shell.exec( file_name )
{
// 메모리 로더가 실행파일 포맷을 해독합니다. PE 든 ELF 든..
memory_loader.decode( executable file format )
{
// 아래와 같은 구조를 읽어서
fork.parse( "[ environment_block ][ table ][ code ][ static_data_initilizer ]" ).
// 아래와같이 메모리에 풀어 놓죠
decode( "[ CODE ][ Literal constant / string ][ STATIC DATA ][ HEAP ][ STACK ]" )
{
call main // entry point 를 실행합니다
}
}
}
// 아래와 같은 프로그램을 실행했을 경우
int main()
{
char buffer[256];
char* buffer2 = buffer;
// buffer = buffer2; 불가능 buffer 는 상수 포인터
scanf( "%s", buffer ); // 정석 ( 입력 문자들의 갯수가 sizeof buffer - 1 을 넘을 경우 오류 )
scanf( "%s", &buffer ); // 가능 : 상수 주소의 주소는 원래의 상수
scanf( "%s", buffer2 ); // 정석
scanf( "%s", &buffer2 ); // 위험 : ( sizeof buffer2 를 넘을 경우 오류 )
}
// 다음과 같은 스택 구성을 갖습니다.
stack 증가방향 ->
main.stack scanf.stack
buffer buffer2 parameter2, parameter1 ( format specifier )
[ [256] [4] ] [ [4] [4] ]
여기서 parameter2 는 두 번째 인자로 받은 주소값의 사본이죠. ( call by value )
그 주소값이 상수냐 변수냐는 상관이 없는데,
buffer 가 256바이트가 할당된 0x800000000 주소였고
buffer2 가 0x80000100 주소에 할당된 4바이트 변수였다면,
&buffer2 는 0x80000100 이란 값이 됩니다.
0x80000100 부터 할당된 메모리는 포인터의 크기 ( 32비트에서 4바이트 ) 밖에 없기 때문에,
null-terminated string 을 위한 1바이트를 제외한,
3바이트를 초과한 입력을 받으면 엉뚱한 메모리를 건드리게 되죠.
( 당연하게도 변수 buffer2 에 원래 들어있던 주소값인 buffer 는 파괴됩니다 )
* stack 에 저장되는 순서는 컴파일러에 따라 조금 달라질 수 있습니다.
* main.stack 과 scanf.stack 의 복귀주소 같은 데이타는 설명의 편의를 위해 생략되었습니다.
일단개추하고 오프라인 보기로 저장후 똥싸러감