✔︎ 미션 2.
1. 미션 제목
메모리와 OverFlow 개념 정리
2. 지시문
1) 수업에서 언급되었던 Heap overflow와 stack overflow에 대해서 어떤 경우에 발생이 되는지 서술해주세요.
2) Strcpy와 strncpy의 차이점을 서술해보세요. (어떤 것을 추천하는지와 그 이유에 대해서 서술해주세요.)
3) 메모리 초기화, 복사, 이동, 비교와 같은 함수가 라이브러리에 있습니다. 사용방법을 숙지하고, 간단하게 코드로 구현 후 정상적으로 동작이 되는지 확인해보세요.
3. 핵심 개념
#문자열복사 #string.h
🔔 답안
1) 수업에서 언급되었던 heap overflow와 stack overflow에 대해서 어떤 경우에 발생이 되는지 서술해주세요.
2) strcpy와 strncpy의 차이점을 서술해보세요. (어떤 것을 추천하는지와 그 이유에 대해서 서술해주세요.)
https://blockdmask.tistory.com/348
우선 두 함수에 대해 간단하게 설명해보겠다.
strcpy(char* a, const char* b);
: b에 있는 문자열 전체를 a로 복사하는 함수
strncpy(char* a, const char* b, size_t n);
: n(=number). 복사하는데 n만큼만 복사하는 함수
하지만 strcpy, strncpy 함수를 사용할 때 주의해야할 사항이 있다.
char origin[] = "BlocDMask"; //size = 11(널 종단 문자 포함)
char dest1[20];
char dest2[10];
char dest3[] = "LongLongLongText"; //size = 17(널 종단 문자 포함)
//case 1 : 크기가 큰 빈 배열에 전체 복사한 경우
strcpy(dest1, origin);
//case 2 : 크기가 작은 빈 배열에 전체 복사한 경우
strcpy(dest32, origin);
//case 3 : 꽉 찬 배열에 전체를 복사한 경우
strcpy(dest3, origin);
printf("case 1 : %s\n", dest1); //ok
printf("case 2 : %s\n", dest2); //run time ERROR
printf("case 3 : %s\n", dest3); //ok
case 1 : BlockDMask
case 3 : BlockDMask
위의 코드를 보자.
case 1과 같이 크기가 넉넉한 빈 배열인 dest1[20]에 origin의 문자열을 복사할 경우에 잘 복사되는 것을 확인할 수 있다.
하지만 case 3을 보면 꽉 찬 배열인 dest3에 origin의 문자열을 복사할 경우, 기존 데이터는 나오지 않고 origin만 나오는 것을 확인할 수 있다.
만약 배열 a가 빈 배열이 아닌 이전에 채워진 배열일 때 strcpy함수를 사용하게 되는 경우, 기존에 a에 있던 값은 전혀 나오지 않고 복사한 b의 문자열만 나오는 것을 확인할 수 있다.
왜 그럴까? 그 이유는 널문자(\0)에 있다. 문자열은 \0까지만 출력을 한다. 따라서 strcpy도 문자열을 복사할 떄 \0까지 복사를 하게 되므로
3) 메모리 초기화, 복사, 이동, 비교와 같은 함수가 라이브러리에 있습니다. 사용방법을 숙지하고, 간단하게 코드로 구현 후 정상적으로 동작이 되는지 확인해보세요.
메모리 초기화: memset
메모리 복사: memcpy
메모리 이동: memmove
메모리 비교: memcmp
---------------------
1) 함수에 있는 지역변수들은 모두 스택에 저장된다고 배웠다. 따라서 스택 오버플로우는 시작점 없이 함수가 자기 자신을 계속 호출할 경우 발생하게 된다. 즉, 자기 자신을 계속 호출하는 버그가 있는 프로그램을 실행하면 스택이 넘치게 되어 일어난다.
malloc을 호출하면 메모리를 힙 영역에서 가져온다. 따라서 힙 오버플로우는 malloc을 계속 호출해 너무 많은 메모리를 할당하여 메모리 속 다른 내용을 덮어쓰기 된다. 이런 경우 컴퓨터가 너무 많이 메모리를 쓰다 보면 파일이 열리지 않거나 화면이 정지하든지 혹은 아예 동작하지 않는 상황이 생긴다.
2) strcpy(char* a, const char* b);
: b에 있는 문자열 전체를 a로 복사하는 함수 strcpy는 문자열을 \0까지만 복사하므로 사용할 때 주의해야 한다. 또한 공간보다 복사할 문자열이 클 경우에 메모리 overflow가 발생하게 되면 원하는 결과물을 만들어낼 수 없다. 이를 보완하여 \0에 상관없이 int형 인자를 받아 원하는 길이(n)만큼 문자열을 복사하는 str"n"cpy가 있다. 이는 원하는 메모리 크기만큼만 복사하도록 하기 때문에 overflow가 발생할 일이 없다.
strncpy(char* a, const char* b, size_t n);
: n(=number). 복사하는데 n만큼만 복사하는 함수
3) 메모리 초기화 : memset, 복사: memcpy, 이동: memmove, 비교: memcmp
--------------------------
1) 수업에서 언급되었던 Heap overflow와 stack overflow에 대해서 어떤 경우에 발생이 되는지 서술해주세요.
heap: 동적으로 할당된 변수가 저장되는 영역. (malloc, comalloc 등 함수로 지정)
heap overflow: 변수 메모리 크기가 힙 메모리를 초과하는 경우 발생.
ex) 1. 힙 메모리를 지정 후, free 함수를 지정하지 않으면, 메모리누수가 발생해 힙 오버플로우 가능성 생김.
#include<stdio.h>
int main()
{
for (int i=0; i<10000000; i++)
{
int *ptr = (int *)malloc(sizeof(int));
}
}
ex) 2. 변수 메모리 크기를 지나치게 크게 설정하면, 힙 오버플로우 가능.
#include<stdio.h>
int main()
{
int *ptr = (int *)malloc(sizeof(int)*10000000));
}
stack: 함수 매개 변수, 지역 변수 및 기타 함수 관련 정보가 저장되는 영역
stack overflow: 스택에 너무 많은 변수가 할당 되거나, 함수 호출이 너무 많은 경우
ex) 1. 배열 변수 크기가 너무 클 경우
int main()
{
int stack[100000000];
return 0;
}
ex) 2. 함수 호출이 너무 많은 경우 ( A() 함수를 계속 반복해, 스택 메모리를 계속 차지하게 됨)
void A()
(
A();
)
int main()
{
A();
}
2) Strcpy와 strncpy의 차이점을 서술해보세요. (어떤 것을 추천하는지와 그 이유에 대해서 서술해주세요.)
strcpy:
문자열을 복사한다.
strcpy(dest, origin);
origin에 있는 문자열 전체를 dest로 복사하는 함수.
strncpy:
문자열을 일정 길이만큼만 복사한다.
(str(=string), n(=number), cpy(=copy))를 뜻한다.
char strncpy(dest, origin, size);
차이:
strcpy 함수는 \0 까지 복사한다.
strncpy 함수는 \0 상관하지 않고 n의 길이만큼만 복사한다.
결론:
strcpy 함수는 문자열의 길이를 체크하지 않으므로 버퍼를 초과해 오버플로우가 발생 할 수 있다.
strncpy 함수는 버퍼 오버플로우에 있어 안전하다. 복사할 대상의 크기를 지정하기때문에, 실수를 미연에 방지할 수 있다. 단 null값이 포함 될 수 있기에 문자열을 확인해야 한다. 그러나 strncpy도 큰 사이즈를 넣을 경우, 에러가 날 수 있기때문에 완전히 안전하다고 할 수는 없다
3) 메모리 초기화, 복사, 이동, 비교와 같은 함수가 라이브러리에 있습니다. 사용방법을 숙지하고, 간단하게 코드로 구현 후 정상적으로 동작이 되는지 확인해보세요.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
//복사
char str1[80]="This is the source string";
char str2[80]="This is the target string";
printf("%s\n",str2);
memcpy(str2,str1,sizeof(str1));
printf("%s\n",str2);
//초기화
char str3[20];
char *str4;
memset(str3, 'A', sizeof(str3));
printf("%s\n",str3);
str4 = (char *) memset(str3,'B', 10);
printf("str4 contents: %s\n", str4);
//이동
char str5[20];
memset(str5, 0, sizeof(str5));
strcpy(str5, "Hello world");
printf("original : %s\n", str5);
memmove(str5+6, str5, strlen("Hello world"));
printf("after memmove : %s\n", str5);
//비교
char str6[20]="Helloworld";
char str7[20];
printf("Helloworld를 입력하세요\n");
scanf("%s",str7);
printf("%s",str7);
if(memcmp(str6,str7,11)==0){
printf("일치합니다\n");
}else{
printf("일치하지 않습니다\n");
}
return 0;
}
'Education' 카테고리의 다른 글
[부스트 코딩 뉴비 챌린지 2020] week5_LIVE 강의 (0) | 2020.08.14 |
---|---|
[부스트 코딩 뉴비 챌린지 2020] week6: 자료구조 (0) | 2020.08.12 |
[부스트 코딩 뉴비 챌린지 2020] week5_미션03 (0) | 2020.08.07 |
[부스트 코딩 뉴비 챌린지 2020] week5_미션01 (0) | 2020.08.07 |
[부스트 코딩 뉴비 챌린지 2020] week5_샘플미션 (0) | 2020.08.07 |