• 함수

함수가 return을 넘기는 과정

리턴 값을 CPU의 메모리or레지스터에 값을 복사해 저장한다

그 함수를 호출한 프로그램에서 리턴값이 들어있는 주소를 조사한다

※ 배열은 return이 안된다

 

함수의 원형

- 컴파일러에게 내가 저장한 return의 자료형이 이거야 라고 알려줌

- 매개변수의 타입과 개수를 컴파일러에게 알려줌

- 식별자 생략 가능(하지만 쓰자)

 

함수의 호출시 return처리

- 리턴값을 계산하여 리턴값을 CPU에 넣는다

- 넣을 때 함수머리부분의 정의된 자료형으로 넣는다

 


  • 매개변수

함수에 전달되는 값을 실제 매개변수(argument) 라한다

함수에 전달되어 복사받은 값을 저장한 변수를 형식 매개변수(parameter) 라한다

형식 매개변수는 지역변수로 생성된다

argument의 값을 복사해 parameter로 넣는다

 

그렇기에 둘다 값만 같고 다른 변수다

그 이유로 넣은 a와 b의 주소가 다르고 a의 값이 그대로이다

 

그래서 주소를 사용한다

함수의 정의에 있는 int b [ ]는 호출 될 때 새로 생성되었으며 a와 가르키는 배열의 데이터는 같다

 

근데 Test함수의 정의에 매개변수를 int b[ ]로 배열을 받게끔 사용했다

생성되는것도 배열이 생성될까 궁금했다

 

그래서 사이즈를 받아봤다

 생성되는 타입은 포인터인듯하다

 

이렇게 포인터로 넘어온다.

포인터는 크기에 제한이 없기에 조심하자

 

  • cctype.h

문자관련함수들

 


  • 삼항연산자

구성이다

expression1 ? expression2 : expression3

 

 

expression1이 true면 삼항연산자의 값은 expression2이며, 그 반대인 false면 값은 expression3이된다

 


  • switchcase

어떠한 정수자료형에 따른 분기를 나눌 때 사용하면 편하다

 

구성이다

switch ( integer-expression )

{

     case label1 : statement

     case label2 : statement

     ......

     default      : statement

}

 

integer-expression에 정수형 데이터가 들어가면 이 데이터와 같은 label의 행이 실행된다

 

주의 할 점은 시작된 구문 부터 계속 실행하기 때문에 break를 써주어 탈출해야한다

break를 안 했을 경우

integer-expression은 정수형은 모두 가능하기에 char, enum도 가능하다

 


  • break & continue

break는 나온순간 속해있는 Loop을 탈출한다

2번 반복문안에 break가 실행될때 속해있는 1번,2번 반복문을 탈출하는게 아니라 2번 반복문만 탈출한다

 

 

continue는 continue가 나온순간 뒤의 코드는 무시하고 반복문의 맨 처음으로 돌아가 조건을 확인한다

마찬가지로 속한 Loop을 기준으로 한다

 


  • 간단한 파일I/O

쓰기와 출력의 로직은 비슷하다

open( )으로 파일과 연결 ,연결한 파일에 관한 작업을 하고 , close( )로 파일연결 종료

 

먼저 파일에 쓰기다

<fstream> 에 정의 되어있는 ofstream 클래스는 Output File Stream으로

파일에 데이터를 작성가능한 기능을 가지고 있다

 

파일 읽기

<fstream> 에 정의 되어있는 ifstream 클래스는 Input File Stream으로

파일에 데이터를 프로그램으로 입력해주는 기능을 가진다

파일을 읽고 쓰는 법은 다양하다

 

나중에 더 자세히 나오니 이부분은 일단 어떻게 돌아가는지 로직만 이해하면 될거같다

 

*스트림 나중에 공부

  • End of File

파일의 끝에 도달했을 때 인식하고 프로그램에게 전달할 수 있다

다른 정규문자와 중복되지 않게 #define EOF -1 으로 지정되어있다

stdio.h

 

일단 redirection이라는 개념이 나왔다 File과 관련된 기능같은데

운영체제에서 제공하는 기능이며 입력이나 출력 등을 파일로 한다는 기능 같다

ex) 항상 키보드로 입력을 받았지만 파일의 데이터를 받아 입력으로 처리한다

 

window는 Ctrl + Z 를 누르는 것으로 EOF를 생성한다

^Z = Ctrl + Z

입력한 문자 개수 만큼 1이 출력된다(빈칸,엔터 포함)

두번째 입력했을때(ab^Zcdefg) Ctrl + Z 부분까지 인식하고 1이 3번 나왔다

 

그 뒤의 cdefg도 버퍼에 남았을까 싶어 다시 입력했지만 새로 입력한 문자개수만큼만 나왔다

이유는 EOF를 인식할 경우 그 뒤로는 입력을 받아들이지 않기 때문이다

 

근데 이상한점이 있다 분명 while문에 EOF를 만나면 종료하라고 되어있는데 한번 더 문자열을 입력 받게되는 상황이다

 

이는 밑의 블로그에 자세히 설명되어있다

간단히 하면 다른 문자가 먼저 입력된 상태에서 ctrl + z 를 입력하면 26의 값으로 처리된다고 한다

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=tipsware&logNo=221315155895 

 

[Q&A] EOF를 어떻게 입력하나요?

: C 언어 관련 전체 목차 http://blog.naver.com/tipsware/221010831969 1. 질문 EOF는 'End of file'...

blog.naver.com

ios_base 클래스에서 정의되어 있고
이를 상속받은 iostream, fstream, stringstream 모두 동일하게 작동합니다.

 

cin은 EOF를 인식했을 때 ios_base 클래스에 정의되어 있는 eofbit, failbit 이라는 비트를 1로 설정한다고 한다

이는 ios_base를 상속받은 iostream, fstream, stringstream 모두 사용한다

 

그래서 EOF를 만났는지 안만났는지 알수있는법은 저 비트를 확인하면 되는데

 

eofbit는 cin.eof( ) 를, failbit는 cin.fail( ) 을 사용하면 알수있다

 


  • 2차원배열

말그대로 2차원처럼 보이는 배열이다

초기화

 

사실은 1차원으로 쭉 나열되어있긴하다

 

일차원배열과 비슷하게 [0]과 [0][0]의 주소는 같다 

 


  • if

조건에 따라 실행하는 구문이 생길때 사용한다

 

구성은

if ( test-condition )

   statement

 

test-condition이 참이면 statement를 수행한다

거짓이면 statement를 건너뛴다

 

거짓인 경우 다시 다른 조건을 확인하는 else if

 

거짓인 경우 무조건 수행하는 else

 


  • 논리표현식

한가지 이상의 조건이 논리연산자를 통해 맞는지(True) 아닌지(False) 값을 나타내는 표현식

 

 

1. || (논리합, OR) - 두개의 조건을 검사하며 둘중 하나라도 True면 True리턴 , 

                         그리고 시퀀스 포인트이기에 좌변의 부수효과가 있다면 || 에서 무조건 실행되고 우변이 평가된다

 

b는 0으로 초기화 되어 있다

 

첫조건 b++ > 0 에서  ++는 접미에 있기에 > 보다 연산자 순위가 낮기에 >먼저 실행된다

 

그럼 0 > 0 이므로 false

 

그후에 || 가 시퀀스 포인트이므로 증가연산자가 실행된다(이때  b = 1)

 

그리고 다음 조건인 b > 0 을 실행한다

 

두번째 조건에서는 b가 1이기에 1 > 0 이므로 최종으로 true이다

 

 

 

2. && (논리곱, AND) - 두가지 조건을 검사하고 모두 True여야 연산의 결과가 True이다

 

 

 

3. ! (논리부정, NOT) - 하나의 조건의 값을 뒤집는다 ( True -> False, False -> True )

                             &&, || 보다 우선순위가 높은 편이다

 

논리부정은 0(Null)인지 아닌지 체크하는데 편리하다

 

 

  • 복합구문&콤마연산자

여러구문을 하나의 구문처럼 간주하는 것

 

중괄호를 사용해 블럭을 생성하는 방법

 

콤마연산자를 이용한 방법이 있다

 

복합구문의 예로 for의 Loop Body는 하나의 구문이어야 하는데

복합구문을 이용해 여러 구문을 실행하게 하는것이였다

콤마연산자도 마찬가지로 복합구문을 만들 수 있다

다만 밑에 처럼 선언과 같이 사용하면 변수 이름을 분리시킨다 하여 분리자 라고 한다

위에 출력값이 20 과 40이다

콤마 연산자는 왼쪽의 구문을 먼저 실행하고 오른쪽의 구문을 실행하는 시퀀스 포인트라고 한다

그래서 a = 20이 들어가고 b = 20 * 2이 되어 40이 출력이 되었다

 


  • 관계표현식

각 연산의 결과가 bool형으로 나온다

 


  • tpyedef ( define & using )

typedef는 기존 데이터형의 별명을 만드는 방법중 하나다( 그외 define, using)

 

구성이다

typedef typeName 식별자

사용하는 방식은 내가 경험하면서 알야겠지만

일단 복잡한 자료형을 간단히 나타내는데 괜찮을거 같고 자료형의 크기가 중요할때 사용해도 괜찮을거 같다

 

define으로도 가능하다

 

#define 을 한 줄에 다 쓸수 없을 때

\ 문자를 이용하여 다중 줄로 선언할 수 있다.

단, 다중 줄로 선언할 경우 마지막 줄 에는 \ 문자를 붙이지 않는다.

 

언리얼엔진 헤더파일중 일부분

 

다만 define을 사용하면 이런문제가 있다고 한다

myDatatype으로 생성한 변수 b는 왜 오류가 나지 않을까?

이유는 int*가 아닌 int형으로 생성되었기 때문이다

 

myDatatype a, b 를 전처리기에서 변환하면

int *a, b 로 변환되기에

a는 int * 으로 생성되고

b는 int 로 생성 되었기 때문이다

 

그렇기에 자료형의 별칭을 만드려면 define은 비추다

 

그리고 typedef말고 using을 사용해서도 정의할 수 있다

 

그럼 typedef와 using의 차이는 무엇인가?

templete의 사용 유무다

using 같은 경우 템플릿을 사용가능하나

typedef 같은 경우 템플릿을 사용하지 못한다


  • 문자열 비교

c 스타일 - strcmp( const char * 1, const char * 2) 사용

 

훨씬 편한 string은 == 사용하여 비교 가능

 


  • while

루프 몸체와 조건 검사부분으로 이루어진 반복문

 

for과 같이 조건이 true면 루프몸체를 실행한다

 


  • do while

while로직이 "조건검사 ─> 루프몸체 실행" 이라면

 

do while은 "루프몸체 실행 ─> 조건검사" 으로 실행부터하고 검사한다

 

조건이 true면 다시 몸체 실행을 하는 것 도 같다

 


  • Range based for loop

C+11에서 추가된 for의 형태

조건부 구성이다

for( range_declaration : range_expression )

 

range_declaration - 변수의 선언, range_expression의 배열 원소 타입으로 지정한다

range_expression - begin( ), end( ) 함수가 정의된 객체 혹은 braced init list

 

 

braced init list는 중괄호를 사용한 초기화 문법인데 아마 이걸 사용한 데이터를 뜻하지 않나 싶다

단순 동적배열에 begin이나 end가 내부적으로 정의 되어 있는지 모르겠지만

(아마 안되는 듯 싶은데.. 검증해야한다)

일단 braced init list내에 속해 있기에 가능한거같다

 

밑의 링크는 braced init list

https://en.cppreference.com/w/cpp/language/list_initialization

 

range_declartion은 range_expression원소와 자료형이 달라도 자동적으로 캐스팅을 해줌으로

같지는 않더라도 최소 캐스팅이 가능한 자료형이여야한다

 

밑의 링크는 ranged based for이 설명된 사이트

https://en.cppreference.com/w/cpp/language/range-for

밑의 Explanation은 위의 사이트에서 나온 설명이다

정말 기존 for문에서 새로운 코드가 아니라 내부적으로는 위처럼 기존 for문이 작동하나 보다

 

 

보통 밑의 코드처럼 사용하는데

auto를 이용해 자료형을 받는데 편리함을 취하고

&를 이용해 복사비용을 줄이면서 값까지 변경 할 수 있는 방식을 많이 사용하는 듯 하다

 

조건부 배열 부분에 배열이름을 사용했다

처음에는 배열이름은 곧 주소이기도 하니까 포인터를 사용 할 수 있지 않을까 생각을 했지만

그렇게 되면 for문은 그 주소가 가진 배열의 크기를 알지 못하기에 사용 할 수 없다

그렇기 때문에 range_expression부분에 들어오는 데이터에 크기를 알수있는 데이터만 가능한가보다

시도했는데 안된다

그러다 함수내에서 매개변수 받아  ㅅㅂ 어떻게 사용하지? 하다가 이렇게 자료형을 구체적으로 적어주는 걸 생각했다

*가 아닌 &를 사용한건 배열 그 자체의 자료형을 가져오려 사용했다

 

근데 이렇게 사용하다가는 너무 불편할거 같아 템플릿을 이용했다

편안..

 

braced init list 에 있는것중 이런것도 있어 가능한지 확인했다

 

  • stl vector & stl array

기존 정적배열의 관리를 쉽게해주는 템플릿 클래스

 

에서 가변적으로 크기를 쉽게 조정 할 수 있게 만든 템플릿 클래스

 

 

vector의 경우 배열의 크기를 런타임중에도 계속해서 변경 할 수 있는 특징이 있다

내부적으로 new delete를 사용한다

 

array의 경우 크기는 컴파일타임시 초기화를 해야 해 크기가 정적이나

대입연산자의 가능, 배열 크기 이상의 값을 참조했을 때 예외를 반환하는등 좀 더 편하게 다룰 수 있다

 


  • 표현식

값, 또는 값 + 연산자 의 조합으로 이루어진 명백한 하나의 값을 가지는 식

 

일단 지금까지 공부한걸로는 세미콜론을 뺄때 값이 있는 것들은 표현식이 되는거 같다

 

선언, 반복문 등은 표현식이 아니다

리턴문도 표현식이 아니라고 하는데 이건 좀 더 봐야할듯

 


  • for

구성

// 세 개 표현식(expression)으로 이루어진 제어부분
for( Loop Initialization ; Loop Test         ; Loop Update ) 
    =init-expression 	   =cond-expression    =loop-expression 
{
      Loop Body;
}

 

순서

Loop Init ─> Loop Test  ─True─> Loop Body ─> Loop Update ─> Loop Test ....

                           │

                           └──False─> 종료

 

 

제어 부분의 세가지 부분은 모두 생략 가능하다 ( 모두 생략시 무한루프 )

 

 

init-expression, loop-expression은 ' , ' 으로 여러 구문을 사용할 수 있다

※' , '를 cond-expression에 사용을 해도 오류는 나지 않으나 아마 정상 작동 안될 확률99%다

 

 

init-expression에 선언한 변수는 for문 안의 지역변수다

for문이 종료되면 사라진다

※단 구형c++ 경우 루프 앞에 선언한 것으로 인식해 삭제하지 않는 경우도 있다

 

 

책보다 문서가 더 정리가 잘되어있다

https://docs.microsoft.com/ko-kr/cpp/cpp/for-statement-cpp?view=msvc-160#remarks 

 

for 문 (c + +)

Microsoft Visual Studio c + +의 표준 c + +에 대 한 참조입니다.

docs.microsoft.com

 


  • 증가 연산자 & 감소연산자

두개 모두 접두(++a), 접미(a++) 방식으로 사용 가능

 

접두식으로 했을 경우와 접미로 사용했을 경우 연산자 순서가 차이가 많이 나니 주의

 

 

 

한 구문에 너무 많이 사용하면 한대 맞을 수 도있다

int a = 3 * a++ - (34 - --a)/++a;

 

포인터와 함께 사용할 수 있다

접두형 끼리 붙었을때 (++*a) 오른쪽에서 왼쪽으로 실행하면 된다고 생각하면 된다

 

++*a를 예로 *가 ++보다 오른쪽에 있으니 먼저 실행한다.

= a포인터에 들어있는 값( a[0]의 값  )

 

그 후에 왼쪽에 있는 ++가 왼쪽에 있었으니 다음으로 실행된다

여기서 ++가 되는 대상은 단순 a가 아닌 ' * ' 를 실행시킨 *a라는 점

= *a의 값에 ++ (a[0]은 1이며 ++하면 2가 된다)

 


  • 부수 효과 & 시퀀스 포인트

간단하게 부수효과는 수식이 진행될 때 변수에 값이 변경되는 효과

 

 

시퀀스 포인트는 부수효과,특히 접미어 방식이 일어나는 시점을 명확히 알 수 있게 해주는 시점을 나타낸다고 보면 된다

포인트로는 수식의 끝, 세미콜론, While루프의 검사 조건 ...등이 있다

 

위의 코드중 접미에 붙은 ++ 가 일어나는 순서와 시점은 구체적으로 알 수 없다

 

다만 시퀀스 포인트(위의 코드에서 ' ; ' )에서 모두 실행이 되었다고 알수있다

 

이 지점에 왔을 때는 모든 부수효과가 실행 완료 됐다 라고 알려주는 것 이게 시퀀스 포인트의 의미

 


  • 접두어 & 접미어 방식

모두 부수효과가 나타난다 가정시에

 

접두어 방식은 기본값에 부수효과를 적용하고 리턴한다

 

접미어 방식은 기본값을 복사하고 복사한 값에 부수효과를 적용하고 리턴한다

 

이 차이가 있으므로 접두어 방식이 조~~~~~~~~금 낫다고 한다

 

 

나중에 클래스사용시 ++나 -- 를 오버로딩하여 사용할 수 있는데

 

크기가 큰 클래스는 복사비용이 꽤 들테니 둘다 사용해서 상관없다면 접두어 방식을 사용하는 습관을 가지자

 

 

  • 도트 멤버 연산자 & 화살표 멤버 연산자

둘 다 멤버데이터를 참조 할 때 사용한다

 

차이점이라면

 

도트 멤버연산자 - 객체에 사용

 

화살표 멤버연산자 - 객체의 주소에 사용

pttrA 같은 경우

(*pptrA) = 객체를 가르키는 주소

이니까 ->만 붙이면 되겠다

 

 


  • 데이터의 저장공간

Stack(자동공간)

지역변수가 저장되는 영역 LIFO 구조로 되어있다

해당 변수가 속한 스코프가 끝나면 자동으로 메모리 해제된다

 

Code&Data(정적공간)

전역변수가 저장되는 영역 프로그램이 종료될 때 메모리 해제된다

 

Heap(동적공간)

책에서는 Free store와 같다고 한다

근데 new로 할당하면 free store이고 malloc으로 할당하면 heap 뭐 이런 소리도 있던데

일단 내가 사용하고 있는 VC++에서의 new는 내부적으로 malloc이 실행되기에 그냥 같은 말이라고 생각한다

 

이 책 포인터부분에서 이 저장공간을 작성했다는건

사용자가 만든 함수 내부에 지역변수로 포인터써서 동적할당하고 해제 안했을때의 메모리 릭 문제를 강조하는거 같다

 

※메모리에 대해 좀 더 공부


  • 변수형의 조합(포인터 장난)

파트 이름은 변수형의 조합.. 이지만 그냥 배열, 구조체에 포인터를 이용할 수 있다 라는 내용이다

 

예제 비슷하게 장난 같은걸 쳐봤다

3번은 왼쪽부터 쭉 읽으면 논리적으로는 완벽해보인다만 오류가 나온다

 

그 이유는 연산자 실행 순서 때문인데

 

모든 식에서(괄호없는 수식) * 보다 . 가 먼저 실행되기 때문에 

 

(arr+1).member 가 실행되는것이다

 

그렇기에 괄호를 한번 더 쳐주어서 *가 먼저 실행되게 하면 정상 실행된다

 

안쓰던 더블포인터랑 포인터 배열 사용 했는데 장난치다보니까 나도 헷갈리더라ㅋㅋㅋㅋㅋ

미래의 나에게 알려준다....

 

 

  • 문자열 상수

배열의 식별자   =    배열의 첫번째 데이터의 주소

(밑에서는 a)

문자열 상수      = 문자열의 첫번째 문자 주소

(밑에서는 "ABCDEFG" , "Is english")

 

문자열은 첫번째 문자의 주소부터 null값 까지 데이터를 찾는 방식으로 사용이 된다

 

그렇기에 저 "Is english"도 문자열이기에 메모리 어딘가에 저장이 되고

첫번째 문자의 주소가 있을 것이고 null값 또한 있을 것 이다

 

첫번째 주소는 "Is english" 이 자체로 첫번째 문자의 주소를 나타낸다

 


 

쉽게 "ABCDEFG"로 확인한다

위에 말처럼 "ABCDEFG" 는 문자열의 첫번째 문자 주소가 될수도있다.

 

(int*) 을 붙여준 이유는 안붙이면 cout가 문자열주소 로 파악하고 문자열을 출력하기때문에

주소를 출력하려고 변환했다

 

"ABCDEFG"가 가진 주소는 00B0AB30, 그 주소로 가 무슨 데이터가 있는지 확인한다

 

41이 들어있다, 메모리는 16진수형태로 나타나며 41은 10진수로 65다

 

65는 아스키 코드로 'A' 이므로

 

"ABCDEFG" 가 'A'의 주소를 가지고 있다고 볼 수 있다


 

컴파일러마다 다르지만 같은 내용이 담긴 문자열 상수가 여러개가 사용되면

 

하나로 취급하여 하나의 주소로 사용 하는 경우도 있다고 한다

[메모리에 하나만 저장하여 쓰인다는 말]

계속해서 작성중 입니다.


 

Malloc & new

 


  • malloc은 초기값을 설정할 수 없다, new는 가능하다

 


  • malloc은 생성자가 호출되지 않는다, new는 생성자가 호출된다
더보기

 

 

eh vector constructor iterator에서 생성자 호출?

 

 


  • malloc은 Realloc으로 메모리블럭의 재할당이 가능하다, new도 실행하다?
더보기

구글링을 하면 new는 realloc이 되지 않는다는 글이 많다.

 

물론 사용안하는게 정신건강에 좋겠지만

 

그래도 실행은 되지 않을까? 하는 마음에 테스트 해봤다

 

밑의 코드로 malloc에서 realloc을 하였을 때, new에서 realloc을 하였을 때 를 메모리 디버깅으로 확인해 볼것이다

 

먼저 malloc에서 realloc일때다

 

realloc 실행 전
realloc 실행 후

 

realloc이 다른 주소를 뱉어내는 바람에 원래 들어 있었던 값 9가 다른 주소로 옮겨지는건 확인했지만

우리가 원한 16바이트 만큼 할당이 된건지 알 수 없다

쥰내 안나와서 코드좀 덧붙였다

위의 사진에서 realloc으로 재할당 받는걸 볼 수 있다

 

저 일정하게 채워져 있는 cd와 fd가 무슨 뜻이 있을거 같아서 검색해봤는데 힙에서 넣어주는 값이라고 한다

앞뒤의 fd는 가드 바이트라 하고 cd는 초기화가 되지 않았다는 뜻이라한다

이 글에 자세히 나와있다

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ruvendix&logNo=220905335341 

 

 

아무튼 이제 new로 확인해보겠다

진짜 같은 주소 안나와서 가챠하는 기분이였다

마찬가지로 원래 있던 값 9가 있으며 앞뒤로 가드바이트가 있으며 빈 영역에 cd로 채워져있다

 

이건 realloc이 실행됬다고 생각을 한다

 

new도 realloc이 되기는 한다

 


  • mallock과 new의 반환형
더보기

malloc은 void * 를 반환한다

 

new는 자료형을 추가로 입력받아 자동으로 캐스팅하여 반환해준다

 

근데 사실 차이까지라고 해야 하나 싶다 그럴거면 그냥 이름도 차이난다고 하지


  • new는 내부적으로 malloc을 사용한다
더보기

 

위에 있는 코드를 어셈블리어로 F11을 눌러서 계속 들어가 확인해 보겠다

 

1. new의 실체인 operator new가 call이 된다

1

 

2. operator new가 있는 곳으로 간다

2

 

3. 들어가보면 malloc이 나와있다

3

 

 

4. 과연 같은 malloc일까? 하여 malloc의 실행 주소가 같은지 확인해본다

4

 

5. 먼저 new의 malloc이다

5

 

 

6. malloc의 malloc이다

6

 

7. 두 함수 모두 0172E340 부터 malloc이 실행된다 이를 통해 같은 malloc이라고 생각을 하고

new의 구현에 있어서 다르겠지만 현재 사용하는 VC++의 new는 내부에서 malloc이 실행된다고 생각한다

 


  • __declspec(allocator) [진행중]
더보기

먼저 New가 실행시에 실행되는 함수 operator new이다

new에 F12를 눌러 확인할 수 있다 // _VCTRT_ALLOCATOR에 F12를 눌러 확인할 수 있다

_VCRT_ALLOCATOR 이 __declspec(allocator) 으로 define되어 있다

 

 

이번엔 malloc의 실 함수이다

여기도 비슷하게 생긴 _CRTALLOCATOR 이란게 있다

여기도 __declspec(allocator)이 나온다!

 

두개에 모두 들어있기도 하고 ALLOCATOR라는 단어가 들어있어서

메모리 할당 요청에 근접한 기능이 있는가 해서 알아보았다

 

 

https://docs.microsoft.com/ko-kr/cpp/cpp/declspec?view=msvc-160 

 

__declspec 이란 대강 뒤에 붙는(ex 위에서 allocator) 특성? 같은걸 저장소 클래스에 지정할 수 있게 해주는 키워드 같다

 

그럼 이 allocator가 특성이라 하니 살펴봤다

 

 

https://docs.microsoft.com/ko-kr/cpp/cpp/allocator?view=msvc-160 

allocator 선언 지정자는 사용자 지정 메모리 할당 함수에 적용 되어 ETW(Windows용 이벤트 추적) (ETW)를 통해 할당을 표시할 수 있습니다.

 

잘 모르겠지만 allocator라는 특성을 설정하고 ETW로 무언가 디버깅?? 같은걸 할수 있다는 말 같은데

ETW 문서도 보았다

 

 

 

https://docs.microsoft.com/ko-kr/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-

https://docs.microsoft.com/ko-kr/visualstudio/profiling/custom-native-etw-heap-events?view=vs-2019 

ETW (Windows 용 이벤트 추적)는 사용자 모드 응용 프로그램 및 커널 모드 드라이버에서 발생하는 이벤트를 추적하고 기록하는 메커니즘을 제공합니다. ETW는 Windows 운영 체제에서 구현되며 개발자에게 빠르고 안정적이며 다양한 이벤트 추적 기능 세트를 제공합니다.
Add the __declspec(allocator)
 decorator to any function in your custom heap manager that returns a pointer to newly allocated heap memory. This decorator allows the tool to correctly identify the type of the memory being returned. For example:

최종적으로 보아하니 __declspec(allocator)는 직접적인 할당의 요청 이런게 아니라 그냥 단순 속성을 정하고

 

디버깅을 할때? 그런 용도로 사용되는거 같다..

 

V가 붙고 안붙고의 차이는 모르겠다..

 


 

delete [ ]

 

 

 

new로 할당 받은 배열 포인터의 해제다

 

delete [ ] 포인터   로 해제를 한다

근데 사실 delete만 사용해도 해제가 된다

[객체 배열 같은 경우에는 소멸자 문제가 있음]

delete 전 // array를 동적 할당 받아옴 각 1, 2, 3 이 들어오는걸 볼수있다
delete 후 // int * 형을 해제 시켰을 뿐인데 모두 해제가 되는 기적을 본다

 

근데 우리가 몇개의 배열을 할당 받은 줄 알고 시작주소만 넘겨주어도 모두 해제가 이루어지는가?? 궁금했다

 

 

일단 사전 지식을 알아야 이해할 수 있었다

 

1. 일단 하나의 프로그램이 시작되면 그 프로그램에게 하나의 힙메모리가 주어진다 이는 Default Heap이라 한다

   (Default Heap, Default process heap 이렇게 부르는 듯 하다)

 

2. Default Heap은 다양한 메모리크기의 요청에 응답하려 여러 메모리의 크기로 나누어져있다

   이 나누어진 메모리들을 메모리 블럭 이라 한다

 

3. Windows에서 이 Default Heap을 관리하는 Heap manager라는 시스템이 있다

 

4. 우리가 힙에 메모리할당을 요청하면 이 HeapManager가 Default Heap에서

   요청한 크기에 알맞는 메모리블럭을 찾으면 그 첫번째 주소를 반환한다

 

5. 이때 Heap manager에 지금 할당해 준 크기를 저장한다

우리가 free나 delete로 시작주소만 넘겨도 모두 해제가 될 수 있었던 이유는
저 Heap manager에 할당해 준 크기가 저장되어 있기 때문이였다
[ 힙매니저에 저장되는 방식이라던지, 어디에있고 어떻게 관리되는 부분은 아직 내게 필요하지 않은 부분같다 ]

 

6. 여기까지 malloc 의 대략적인 할당 과정이다.

 

※ new의 동적할당과 new의 배열동적할당 어셈블리 차이 확인하기

 


 

작성시 많은 도움이 된 글

https://kfgd.tistory.com/18?category=974115 

 

검증이 어렵고 어려운 내용이 많아 틀린부분이 많을거 같습니다.

 

잘못된 부분이 있다면 알려주시면 감사드립니다.

+ Recent posts