// 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 의 복귀주소 같은 데이타는 설명의 편의를 위해 생략되었습니다.