22.03.17 메모리
메모리 주소
- 16진수로 표현
- 16진수는 수 앞에 0x를 붙여서 표현 (0xFF)
- 메모리 주소를 받는 연산자 : &
- 주소에 있는 값을 받는 연산자 : *
- 특정 값의 메모리 주소는 메모리 주소에 할당된 값을 "가리킨다"
- 아래와 같은 방식으로 Pointer 역할을 하는 변수를 선언할 수 있다.
#include <stdio.h>
int main(void)
{
int n = 50;
int *p = &n;
printf("%p\n", p);
printf("%i\n", *p);
}
- p 는 n의 메모리 주소를 저장한 "Pointer"이다.
- p 는 int data type의 변수를 "가리킨다"
문자열 (String)
- THERE IS NO STRING
- string s = "EMMA" 라고 할 때, s는 결국 E(s[0])의 주소를 가리키는 Potinter이다.
- 원래는, char *s = "EMMA" 라고 할 수 있다.
- typedef char *string : char * (char의 주소를) string 이라는 자료형으로 선언할 것이다.
- 문자열이란, char의 첫 번째 주소를 기억하고, 끝은 \0으로 끝난다는 것이 규칙이다.
- 문자열 변수에는 문자열이 있는 메모리의 주소가 저장된다. (char *s = "...")
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
int main(void)
{
string s = get_string("s: ");
string t = s;
t[0] = toupper(t[0]);
printf("s: %s\n", s);
printf("t: %s\n", t);
}
- 그래서, 이렇게 설정하면, s의 주소값이 t라는 변수에 씌워지기 떄문에, t의 첫 글자를 대문자로 바꾸면 s의 첫 글자 또한 대문자로 바뀌게 된다.
- 이럴 때 사용하라고 있는 것이 "메모리 할당 함수"인 "malloc"이다.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s = get_string("s: ");
char *t = malloc(strlen(s) + 1);
for (int i = 0, n = strlen(s); i < n + 1; i++)
{
t[i] = s[i];
}
t[0] = toupper(t[0]);
printf("s: %s\n", s);
printf("t: %s\n", t);
}
- malloc() 함수의 파라미터로 메모리 크기를 설정 해줄수 있다.
- 위 예시에서는, \0까지 생각해줘야 하기 때문에 입력받는 string 길이에 +1을 해서 파라미터로 넘겨주었다.
- 그리고, null terminator인 \0까지 복사하기 위해, i < n + 1 로 작성하여 for 구문을 실행했다.
- 이는 간단하게 strcpy(t, s); 이렇게 표현해줄수 있긴하다.
메모리 할당 & 해제
- malloc : memory allocation. 할당한 메모리의 첫 byte 주소를 돌려준다.
- 메모리 할당 : 메모리의 일부를 가져와서, 그 곳을 가리키는 "Pointer"를 주는 것.
char *t = malloc(strlen(s) + 1);
- 메모리를 할당 받았지만, 해제 해주지는 않았음. ( > free를 사용하여 해제해줘야 함)
- free : 할당 되었던 메모리를 다시 반환함. 반환 해야, 프로그램이 더 많은 메모리를 사용할 수 있음. 사용하지 않는 메모리는 반드시 해제할 것.
- 메모리 확인 디버깅은 valgrind를 사용하였다.
- 이렇게 메모리 누수를 확인할 수 있다. 함수의 마지막 줄에 free(t);를 추가해서 해제하자.
- free를 이용하여 해제를 하지 않으면, 메모리에 저장한 값은 "쓰레기 값"이 된다.
- buffer overflow : 할당 메모리 공간을 넘어 접근하는 것. (아래 예시)
int *x = malloc(10 * sizeof(int));
x[10] = 0; // Buffer overflow에 해당함.
메모리 교환, Stack, Heap
메모리 안에는 데이터 저장 구역이 나뉘어져 있다.
- Machine code = compiled binary
- Globals = 전역 변수
- Heap : malloc이 메모리를 할당하는 곳 (Top -> Bottom)
- Stack : 함수가 호출될 때 지역변수가 쌓이는 공간 (Bottom -> Top)
- main 함수의 변수들은 stack에 저장
- 하지만, 해당 메모리 구조는 그닥 좋은 구조가 아님. malloc이 많이 호출될수록, 함수가 많이 호출될수록, heap과 stack의 영역이 서로 커질거고, 어디선가 두 메모리의 영역이 충돌하게 되어있음.
- Heap overflow(malloc 과호출) & Stack overflow(함수 과호출)
- -> Buffer overflow 발생 : 화면 정지, 파일이 안열리거나 동작하지 않는 그런 상황이 발생함..
#include <stdio.h>
void swap(int a, int b);
int main(void)
{
int x = 1;
int y = 2;
printf("x is %i, y is %i\n", x, y);
swap(x, y);
printf("x is %i, y is %i\n", x, y);
}
void swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
- swap 함수는 스택에 쌓여지고, 순차적으로 실행된 후, 완료되면 버려진다. (더이상 사용되지 않음)
- a, b는 x, y의 복사된 값을 사용하였기 때문에, main 내의 x, y가 영향을 받지 않았다. (&a != &x, &b != &y)
- 근본적 해결책 : x, y의 주소를 알려줘서, swap 함수가 그 주소로 간 후, 해당 값을 바꾸게 해야 함.
- 즉, swap 함수의 a, b가 x, y를 "가리키게" 해야 함.
#include <stdio.h>
void swap(int *a, int *b);
int main(void)
{
int x = 1;
int y = 2;
printf("x is %i, y is %i\n", x, y);
swap(&x, &y); // x, y의 메모리 주소를 넘겨줌
printf("x is %i, y is %i\n", x, y);
}
void swap(int *a, int *b) // 넘겨받은 주소를 a와 b에 저장
{
int tmp = *a; // a 주소에 저장된 값을 *로 불러와서 tmp에 저장
*a = *b; // a 주소에 저장된 값을 b 주소에 저장된 값으로 변경
*b = tmp; // b 주소에 저장된 값을 tmp 값으로 변경
}
파일 읽기, 쓰기
- 변수의 값을 바꾸고 싶다면, 값으로 전달하면 안됨(복사본이 전달되고, 사라짐) &x 와 같이 주소를 전달해줘야 함.
- scanf("%s", s); -> 저장 할 주소를 넘겨줌. array의 경우, 첫 byte 주소를 넘겨받음.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// Open file : FILE 이라는 새로운 자료형을 가리키는 포인터 변수 file
FILE *file = fopen("phonebook.csv", "a"); // 파일 내용 저장 csv : comma seperated value
// Get strings from user
char *name = get_string("Name: ");
char *number = get_string("Number: ");
// Print (write) strings to file
fprintf(file, "%s, %s\n", name, number);
//Close file
fclose(file);
}
- 항상, 포인터와 메모리 주소 개념에 대한 내용을 상기시킬 것.
Author And Source
이 문제에 관하여(22.03.17 메모리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kimsy8979/22.03.17-메모리저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)