2011-02-14 4 views
2

C/C++로 프로그래밍했지만 꽤 많은 시간이 걸렸습니다. 아마도 저는 잘 쓰여지고 권위있는 자료를 읽지 않았을 것입니다.컴파일 된 프로그램이 운영 체제와 상호 작용하는 방법에 대한 질문

(1) Linux/Unix의 경우, 얼마나 큰 사용자 프로그램이 될 수 있습니까? 프로그램이 가질 수있는 스택의 최대 크기? 사용자 프로그램이 사용할 수있는 힙의 최대 메모리 양

(2) C 실행 파일에는 데이터 섹션, 코드 섹션 & 스택 섹션이 있다는 것을 알고 있습니다. 프로그램이 많은 재귀 호출을받는다면 많은 양의 스택이 필요합니다. 이 미리 정의 된 크기의 스택입니까, 재귀가 증가하면 커집니다. 성장의 경우 프로그램의 주소 공간도 동적으로 증가해야합니까? 그렇다면 프로그램을 느리게하지 않겠습니까?

(3) 마찬가지로 프로그램 mallocs가 실행될 때 런타임에 힙의 메모리가 프로그램에 할당되면 프로그램의 주소 공간에 힙 영역을 추가해야합니까? 따라서이 경우에도 프로그램의 페이지 테이블을 업데이트해야합니다. 내 이해가 맞습니까?

(4) 하나의 실행 파일을 구성하기 위해 결합하려는 두 파일에 동일한 이름의 전역 변수를 사용할 수없는 이유는 무엇입니까? 오브젝트 파일의 모양을 밝히는 데 도움이됩니다.

추가 :

나는 http://www.open-std.org/jtc1/sc22/wg...docs/n1256.pdf에서 ISO C99 표준을 읽고있다. 한 번 이상은 프로세스라는 연결하여 동일한 객체 또는 함수를 참조하도록 할 수있는 다양한 범위 또는 동일한 범위에서 선언 확인 시험 과학 ERS 1 확인 시험 파이 어의

6.2.2 연계 : 그것은 42 페이지에 말한다 외부, 내부 및 아무도 연결의 3 개의 종류 가있다.

2 전체 프로그램을 구성하는 번역 단위 집합과 라이브러리 집합에서 외부 연결을 사용하는 특정 식별자를 선언 할 때 동일한 개체 또는 함수를 나타냅니다. 하나의 번역 단위 내에서 내부 식별자 인 을 가진 식별자의 각 선언은 동일한 객체 또는 기능을 나타냅니다. 연결이없는 식별자의 각 선언은 고유 한 엔터티를 나타냅니다.

3 개체 또는 함수에 대한 파일 범위 식별자의 선언에 저장소 클래스 지정 정적이 포함되어 있으면 식별자에 내부 연결이 있습니다. 확인 시험 인터넷 ER 들어

4는 확인 시험 인터넷 ER의 종래 선언이 표시되는 범위 스토리지 클래스 특정한 어 통근 선언 경우 종래 선언 특정한 ES 내부 또는 외부 링크, 나중에 선언에서 확인 시험 인터넷 ER의 연계 이전 선언에서 명시된 연계와 동일합니다. 이전 선언이 표시되지 않거나 이전 선언이 연결을 지정하지 않은 경우 식별자는 외부 연결을가집니다.

5 함수에 대한 식별자의 선언에 저장 영역 클래스가 없으면 함수의 연결은 저장 클래스 지정 extern으로 선언 된 것처럼 정확하게 결정됩니다. 객체에 대한 식별자의 선언에 파일이 있으면 범위 및 스토리지 클래스가 지정되지 않은 경우 해당 링크가 외부입니다.

2 개의 소스 파일에서 int int와 같은 변수를 선언하면이 내용을 읽은 것 같습니다. 둘 다 규칙 5와 4에 따라 외부 연결을 가지고있다. 그리고 규칙 2에 따라, 둘 다 같은 대상을 참조해야한다.그러면 컴파일러가 왜 문제를 일으 킵니까? 표준에서 2 개의 소스 파일에서 이것을 선언 할 수 없다는 암시가 있으며 컴파일 오류가 발생합니다.

감사합니다.

+0

http://www.linuxhowtos.org/Tips%20and%20Tricks/ulimit.htm – Anycorn

+5

-1. 네 가지 질문은 네 가지 질문으로 게시해야하므로 앞으로 검색 할 수 있습니다. 현재 제목을 검색 할 수 없습니다. –

답변

3
: 당신이 다른 TU가있는 같은 변수를 사용하지 않으려면 물론, 당신은 아마 당신이 네임 스페이스 범위 내 정적 또는 익명의 네임 스페이스 얻을 같은 "내부"이름을 원하는 귀하의 질문 - 응답에서

  1. 대부분의 운영 체제는 각 프로그램이 가상 메모리를 사용은 주소 공간을 모두 소유하고 생각합니다. 이것은 대개 프로그램의 크기 제한이 시스템의 실제 메모리 크기에서 보통 유효하지 않은 (NULL로 생각하는) 포인터와 커널 용으로 예약 된 소량의 메모리를 뺀 것을 의미합니다. 최대 메모리 제한은 일반적으로 플랫폼에 따라 다르지만 일반적으로 32 비트 시스템에서는 프로그램이 거의 4GB의 메모리를, 64 비트 시스템에서는 그 이상의 메모리를 사용할 수 있습니다. 물론 가상 디스크의 크기를 제한하는 디스크 크기도 고려해야합니다. 이론 상으로는 메모리에 맞지 않는 프로그램을 작성할 수는 있지만 임베디드 장치를 사용하지 않는 한 (이것이 정말로 우려되는 부분인데) 이것이 일어날 것 같지 않습니다.

  2. C 및 C++를 비롯한 대부분의 프로그래밍 언어에서 스택 크기는 컴파일시 고정되지 않고 대신 프로그램이 실행될 때 작아지며 커집니다. 그러나 스택이 커지는 방식은 대개이 값이 저렴합니다. 더 많은 공간을 확보하려면 스택 포인터를 조금만 부딪 치면됩니다. 프로그램에 현재 할당되지 않은 메모리로 이동하게되면 OS는 일반적으로 스택이 현재 존재하는 가상 주소와 페이지를 연결하여 메모리를 할당합니다. 이는 힙 할당보다 훨씬 빠릅니다. 이 작업을 수행하는 데 드는 비용은 일반적으로 장기적으로 무시할 수 있으므로 스택 메모리를 사용하지 않는 것이 좋습니다. 흥미롭게도 몇몇 구식 프로그래밍 언어, 즉 FORTRAN의 첫 번째 화신 인 경우 동적 스택 공간이 없었기 때문에 재귀를 사용할 수 없었습니다. 사실 모든 모던 언어는 이러한 제한을 없앴습니다.

  3. 정확합니다. 더 많은 힙 공간이 필요할 때 페이지 테이블이 힙 공간을 늘리도록 조정됩니다. 많은 메모리 할당자는 익명의 메모리 매핑 파일에 대다수의 메모리를 둡니다.이 목적을 위해 힙 공간을 직접 사용하지는 않지만 원칙적으로 동일합니다. 페이지 테이블이 업데이트되어 새 메모리를위한 공간을 만듭니다.

  4. 다른 파일에 두 개의 전역 변수가 연결되어 있으면 두 개의 오브젝트 파일에 해당 이름의 변수를 참조해야한다는 심볼릭 링크가 포함되어있어 두 개의 오브젝트 파일 모두 정의를 포함하게됩니다 그들은이 이름의 상징을 제공한다고 말했습니다. 링커를 함께 연결하면 링커에서 동일한 심볼 이름이 두 위치에 정의되어 있고 해당 전역 변수의 "인스턴스"로 사용해야하는 것이 확실하지 않기 때문에 오류를보고합니다. 최소한 C에서이 문제를 해결하기 위해 전역 변수 static을 표시하여 내부 연결을 허용 할 수 있습니다. 이로 인해 심볼이 전역으로 내보내지지 않으므로 생성 된 오브젝트 파일은 내부적으로 참조를 분석하거나 이름을 변경하여 다른 파일의 다른 심볼과 충돌하지 않도록 할 수 있습니다. C++에서는 익명 네임 스페이스 기능과 함께이를 사용하여 동일한 효과를 얻을 수 있습니다.

희망이 있습니다. 누구든지 여기에 오류 또는 모호함이있는 경우 알려 주시면 수정 해 드리겠습니다.

+0

그래, 포인터 주셔서 감사합니다 : "하지만, 스택이 커지면 일반적으로 이렇게 저렴 해집니다. 더 많은 공간을 얻으려면 스택 포인터를 약간 튕겨 내야합니다." – xyz

2
  1. 예, 예, 예. bash 또는 man getrlimit에서 "help ulimit"을 참조하십시오.

  2. 스택 크기는 프로그램이 시작될 때 설정되며 증가시킬 수 없습니다. 이전에 사용 된 것보다 많은 스택을 사용하면 주소 공간이 커지지 않지만 메모리 사용량은 증가 할 수 있습니다.

    Google 스프레드 시트 (예 : Google Go와 같이 gcc 및 다른 컴파일러에서 다른 언어로 허용하도록 작업이 진행 중일 때)를 사용하는 경우 "스택에"있지 않은 추가 메모리가 할당됩니다. 스택 포인터가 조정됩니다. 이것은 함수가 호출되고 반환 될 때 동적으로 관리됩니다.

  3. 필요에 따라 힙이 커질 수 있습니다. 이 문제가 발생하는 방법에 대한 간단한 개요는 man sbrk를 참조하거나 various malloc implementations을 참조하십시오. 당신은 그것의 요지를 이해하는 것 같습니다.

  4. 적어도 C 및 C++의 경우 전역 변수는 전체 프로그램에서 으로 정의 된 후에 만 ​​정의 할 수 있습니다. 두 개의 변환 단위 (TU를 .o 파일로 생각할 수 있음)는 동일한 이름의 전역 변수를 사용할 수 있지만 한 번 정의 할 수 있으며 올바른 TU로 선언해야합니다. 나는 오브젝트 파일의 세부 사항을 이해하는 것이 도움이 될 것이라고 생각하지 않지만, C++에서 ODR (One Definition Rule)이라고 불리는 것에 대한 세부 사항을 이해하거나, 사용하는 언어에 상관없이 유용 할 것입니다. 편집에 관한


, 당신은 아마 두 TU가에 int를 정의해야 : 당신은이 작업을 수행 할 수 없습니다

int this_is_a_definition; 

.

extern int this_is_a_declaration; 

그런 다음 해당 변수가 필요한 곳에 헤더를 포함하고 정확히 하나의 TU에 변수를 정의하십시오.

static int local_to_this_TU; 

namespace { 
    int another_local_to_this_TU; 
} 
+0

그래서 성장 가능한 스택 세그먼트에 대해 강한 의견 차이가 있습니다. 일부 증명 링크가 필요합니다. – ulidtko

+0

@ulidtko : 나는 더 분명 했어야했는데, 나는이 편집으로 내가 바라던 것보다 더 많은 것을 동의하지 않는다고 생각한다. 이게 뭐야? –

+0

ulimit에 포인터를 보내 주셔서 감사합니다. 개념적으로 가상 메모리 개념은 프로그램이 물리적 메모리보다 큰 총 가상 메모리만큼 커질 수 있다는 것을 이해했습니다. 그러나이 포인터는 실제 관리자가 sys 관리자가 ' 사용자가 다른 사용자가 시스템을 사용할 수 없게 만들 수 있습니다. – xyz

관련 문제