사용자가 C++파일(파일명.cpp)을 작성하고 컴파일 버튼을 누르면 C++프로그램이 컴퓨터가 읽을 수 있도록 목적파일(파일명.obj)로 바꾼다. 그 후 외부 C++라이브러리나 함수, 객체등을 이용하기 위해 링킹을 통해 코드를 가져오는 작업을 진행한다. 이런 복잡한 과정을 통해 실행파일(파일명.exe)가 만들어 지지만, 오타나 잘못된 참조 등으로 실행시 오류가 생기는 실행파일이 만들어지면 사용자가 디버깅을 통해 수정 후 다시 컴파일을 실행해야한다.
정리
1. 소스 파일 생성(코드 짜기)
2. 컴파일 실행
3. 목적 파일 생성(obj)
3. 링킹(라이브러리, 함수, 객체)
4. 실행파일생성(exe)
5. 완료(오류시 1번으로 돌아가 사용자가 디버깅)
visual studio code에서는 컴파일러가 기본적으로 설치되어 있지 않다. 따라서 컴파일러는 직접 설치해야한다.
파일 경로에 '한글'사용시 컴파일시 error를 출력하거나, 디버깅시 error를 출력한다.
사용자가 코드 실행하면, 이 코드가 메모리에 저장된다.
각 영역에 함수나 변수등이 저장되는 위치가 다르기 때문에 생명주기가 서로 달라진다.
코드영역과 데이터 영역은 컴파일과 링킹과정을 거치면 만들어진다. 이렇게 만들어진 exe파일을 실행하면, 로더라는 함수가 두영역을 메모리에 할당시키는데, 이 과정에서 스택영역을 메모리에 할당(생성X, 임시) 한다. 힙영역은 runtime 때 동적메모리가 필요하면 할당(생성X,임시) 한다.
스택과 힙은 임시영역이다. 이 임시영역을 스택과 힙이 같이 공유한다.
만약 임시영역을 과도하게 할당하려는 시도(ex: int name[1024*1024])가 있다면, 공간할당에 실패하며 에러가 날 수 있다.
전역변수는 1번만 exe파일을 만들 때 생성되는데, 따라서 코드상 여러번 생성한다고 해서 아래처럼 c가 초기화 되는 것이 아닌, c에 계속 값이 추가되어 20을 출력한다. static은 그파일내에서 사용하는 전역변수 지정구문이다.
사용예시
int a=8; // 전역변수:: 컴파일,링킹과정에서 데이터영역
int main() { // 메인함수:: runtime시 스택영역
int b = 1; // 지역변수:: runtime시 스택영역
for(int i=0; i<20; i++){
static int c=0 (이 코드는 1번만 실행)
int c++;
}
return 0;
}
int x;
cin >> x;
int arr[x];
위 같은 선언문은 정상적으로 실행되지 않는다. 왜냐하면, 원래 arr[x]는 스택 영역에 들어갔어야 하나, 스택은 배열의 크기를 동적으로 할당받는것이 불가능하기 때문이다.
따라서, 동적인 크기의 배열을 생성하고 싶다면, new를 통해 힙을 이용해야 한다. 단, 포인터를 반드시 삭제해야한다.
int *arr = new int[x]; // 힙에서 배열공간을 생성해 그 주소를 arr포인터에 저장
delete arr[];
디버깅이란? 오류를 검출하는 과정을 의미한다.
디버깅을 시작하려면 vscode의 실행창에서 F9를 통해 중단점(검사할 범위)를 설정한 후 F5를 통해 디버깅을 시작하면 된다. 이때 코드 왼쪽에 클릭하면 중단점이 생성된다.
(만약, 디버깅없이 exe파일을 실행하고 싶다면, ctrl+F5를 누르면 된다.)
디버깅 모드를 벗어나고 싶다면 빨간원을 전부 눌러 없에면 원래 창으로 돌아온다.
중단점이란? 어떤 점까지만 일단 실행한뒤에 중단하는 것을 의미한다.
디버깅모드에서는 왼쪽에 다음의 항목이 나타난다.

위측에는 위와같은 아이콘이 나타난다. 각 아이콘 순서대로 각각,
1. 다음중단점까지 실행
2. 코드를 1줄씩 실행하며 오류찾기(단, 함수는 무시)
3. 코드를 1줄씩 실행하며 오류찾기(함수도 실행하며, 함수위치로 이동후 1줄씩 실행)
4. 3번중 함수 탈출하고 메인함수로 돌아가기 이다.
아래와 같은 코드가 존재한다.
int main() {
int t;
for(int i=0; i<t; i++){
static int c=0 (이 코드는 1번만 실행)
int c++;
}
return 0;
}
위 코드에서 우리는 t값을 알수 없다.
이런 t값에 어떤 정수를 =을 통해 하나하나 코드를 바꿔가며 입력해 테스트 하지않고 디버깅 모드에서 t에 정수를 넣어 어떤방식으로 처리되는지 확인할 수 있다.
int main() {
int t;
for(int i=0; i<t; i++){
static int c=0;
c++;
};
}
위값에서 t는 어떤 값으로 초기화 하지 않았기 때문에 garbege값이 들어간다. 만약 garbege값이 5라면 5번 for문이 실행되어 c는 5가된다.
이때 디버깅 모드에서 int t이후 for문에서 중단점을 건뒤, 왼쪽 로컬변수 t값을 3으로 수정한다면 어떻게 될까?
반복문이 3번 실행된다. 매우매우 신기한 기능이다!.
만약 for문의 t가 100이라면 50번째 실행 중에 '50번째 실행중입니다'가 정상 출력되는지 어떻게 확인할까? 50번만 클릭할까? 노가다지만 할만하다.
만약 500번이라면 어떻게 처리하겠는가?
이를 위해 중단점을 특정조건에서 실행되게 할 수 있다. 중단점에서 우클릭후 중단점 편집을 클릭한다. 이때 조건을 i===500으로 바꾸면 i===500부터 실행할 수 있다.
#include <iostream>
using namespace std;
int main() {
int t;
for(int i=0; i<t; i++){
static int c=0;
c++;
};
}

한글이 출력때 깨진다면 인코딩 에러라고한다.
이를 UTF-8이나, korean으로 변경하면 해결할 수 있다.
링킹 과정에서 여러개의 라이브러리 코드를 컴파일러가 다운받다 보면, 이름에 중복값이 생겨 어떤 라이브러리의 데이터를 가져와야할지 컴파일러가 모르는 경우가 존재한다.
이런 이름 중복 현상을 막기위해 사용하는 것이 name space이다. 대표적인 표준 C++ name space로 std가 존재한다.
사용 예시)
1. std라는 라이브러리의 기능을 사용하려면, std::cout처럼 가져오는 라이브러리명을 사용하려는 함수 앞에 붙여 써야만 한다.
using std::cout 과 같이 using을 사용한 경우, cout이라는 함수에 한해서 std::라는 라이브러리명을 생략할 수 있다.
using namespace std;와 같이 namespace구문을 사용해주면, 모든std라이브러리에 대해 std::를 생략할 수 있다.
단, std에 존재하는 함수와 자신이 만든 함수명이 중복되어선 안된다.
#include <iostream>
using name space std;
-> cout뿐 아니라, cin등 모든 입출력 관련 패키지도 사용하기 위해 iostream을 사용한다.