소개
기초 게임기술 스터디 그룹 운영
University of Southern California (Computer Science)
게시글
질문&답변
2020.04.29
8:12 경에 질문있습니다.
언더플로우는 한번만 일어났습니다. (0 에서 더 작아질 때 한번만 발생합니다.) 오버플로우는 반대의 의미로 해당 메모리가 이미 표현할 수 있는 최대치에 도달했는데 추가적으로 더 더해질때 일어납니다. 예를들어 0xFFFFFFFF 에 0x00000001 을 더하면 발생합니다. 나머지는 잘 이해하셨습니다!
- 0
- 4
- 141
질문&답변
2020.04.27
포인터변수에 NULL(=0)을 대입한다는것은
"컴퓨터는 주소를 포함해서 수를 저장할때 결국엔 2진수로밖에 저장할 수 없습니다." NULL 과 0 은 사실 의미가 좀 다르지만 컴퓨터가 다르게 표현하기 애매하기에 NULL, 0, '\0' 등을 C 언어에서는 모두 0 으로 표현하는 것입니다. 예를들어 NULL 을 1 이라고 한다면 이번엔 숫자 1과 표현이 충돌하는 문제가 생깁니다. 때문에 그나마 비슷한 의미를 가진다고 볼 수 있는 0 을 쓰도록 약속한 것입니다. (위 방식이 좋다고 말하긴 어렵지만 컴퓨터는 사람처럼 추상적은 개념을 저장하기에는 비효율적입니다... 완전 이과생이죠.) 그럼 NULL 이 담겨있는 포인터를 가지고 접근을 시도하려면 0x00000000 에 있는 메모리를 참조하게 되는 것일까요? 실제로 그렇게 된다면 심각한 보안 문제(NULL pointer dereferencing) 이 발생하기에, 운영체제에서는 올바르지 않은 메모리 위치에 접근하는 것을 막습니다. (가장 간단하고 대표적인 예가 0의 위치를 참조하는 것입니다) 하지만 올바르지 않은 위치를 참조하려고 시도하면 오류가 발생하고 프로그램이 멈추므로 if(ptr != nullptr) 처럼 우선 검사한 이후에 사용하는 것이 좋겠죠?
- 1
- 2
- 537
질문&답변
2020.04.27
8:12 경에 질문있습니다.
해당 예제는 포인터에 언더플로우를 유도하면 어떻게 되는지에 대한 내용인 것 같습니다. 컴퓨터는 주소를 포함해서 수를 저장할때 음수이건 양수이건 결국엔 동일한 2진수로밖에 저장할 수 없습니다. 그렇기 때문에 우리가 C언어에서 메모리를 읽을때 자료형 또는 형식 지정자 등을 꼼꼼히 명시해줘야 하는 것입니다. 예를들어 같은 이진수 1000 0000 라도 1 바이트 (8 비트) 부호있는 정수로 해석하면 -128 이 되고, (2의 보수 표현법에서 맨 앞자리가 1이면 음수로 생각하시면 쉽습니다.) 1 바이트 (8 비트) 부호없는 정수로 읽으면 128 이 되는 것입니다. 이는 음수던 양수던 메모리를 최대한 활용하기 위해서 이렇게 만들었다고 생각하시면 됩니다. (2의 보수 표현법) (음수값 "128" 을 쉽게 구하는 방법은 위의 경우 자료형(메모리 크기) 가 8비트로 되어있는데, 8비트로 표현할수 있는 모든 경우의 수 256. 즉, 이진수 1 0000 0000 값에다가 위의 2의 보수로 표현된 이진수 1000 0000를 빼주면 쉽게 도출할 수 있습니다.) 다시 강의 예제로 돌아가보면 ptr이 원래 가지고 있던 수는 0 입니다. (NULL 이랑 같군요..) 0x00000000 이진수로 표현하면 아래와 같습니다. 0000000000000000000000000000000000000000000000000000000000000000 그다음 ptr = ptr - 2 를 하게 되면 ptr 의 값은 0 에서 -2 * 8 (메모리 접근 단위가 1바이트 씩이고, long long 이 8바이트 크기인 것 배우셨죠?) 즉, -16 로 바뀌어야 합니다. 컴퓨터 메모리에 -16 을 저장하려면 어떻게 적어서 넣어야 할까요? 네 맞습니다. 2의 보수 표현법으로 넣어야 합니다. 따라서 다음과 같이 ptr 에 들어있는 값이 바뀌게 되는 것입니다. 0xFFFFFFF0 이진수로 표현하면 다음과 같습니다. 1111111111111111111111111111111111111111111111111111111111110000 + 강의에서는 아마 실험적인 의도로 포인터의 주소를 부호가 있는 긴 긴 정수형 (%lld) 으로 출력해 본 것 같습니다. 사실상 실제로 프로그래밍을 하실때 이렇게 쓰실 일은 없다고 보셔도 좋습니다. 포인터의 값(주소)를 출력하려면 형식 지정자를 포인터형 (%p) 으로 사용하는 것이 맞겠지요... + 0000000000000000000000000000000000000000000000000000000000000000 에다가 -1 을 하면 어떻게 될까요? 언더플로우가 나면서 1111111111111111111111111111111111111111111111111111111111111111 가 됩니다. 참고 - https://dojang.io/mod/page/view.php?id=32
- 0
- 4
- 141
질문&답변
2020.04.26
메모리공간의 주소?
그럴리가요.. ㅎㅎ 저도 만들어주신 강의보고 배운게 많았어요. 아직 저는 학생 신분이라서 정식(?) 도우미는 조금 부담스럽지만 5월 중순부터는 시간적 여유가 생길 것 같아요. 시험 끝나면 메일 드릴께요.
- 4
- 4
- 1.5K
질문&답변
2020.04.25
질문
좋은 질문입니다 2. 설명을 보충해 드리겠습니다. 컴파일러가 symbol table을 만들면, 링커가 그 심볼들을 찾아서 relocation (offset) table 을 만들어 obj 파일들을 연결시켜 주는 것입니다. symbol 을 간단히 설명하면 함수의 이름이라고 보시면 됩니다. (C++ 에서는 함수의 이름만으로 결정되지는 않습니다) 사실 컴파일러는 함수의 정의부분과 선언(프로토타입)부분이 따로있던 어디에있던 신경쓰지 않고 단순히 별개로 놓고 컴파일을 합니다. 따라서 함수의 이름만 같다면 링커는 연결을 해주는 것입니다. 함수의 선언(프로토타입)만 "헤더이름.h" 에 덜렁 놓고 함수의 정의(바디)를 지워보세요. 컴파일 과정은 정상적으로 되는데 obj 파일들을 링킹하는 과정에서 에러가 발생하는 것을 알 수 있습니다. (링킹 에러 : 함수의 정의에 대한 심볼을 못찾겠습니다!) 아직은 이해가 어려우실 수 있습니다. 시간이 많이 나신다면 C++를 공부하시면서 아래 책을 천천히 읽어보세요. https://book.naver.com/bookdb/book_detail.nhn?bid=9937225
- 5
- 4
- 175