게시글
질문&답변
2020.04.29
8:12 경에 질문있습니다.
언더플로우는 한번만 일어났습니다. (0 에서 더 작아질 때 한번만 발생합니다.) 오버플로우는 반대의 의미로 해당 메모리가 이미 표현할 수 있는 최대치에 도달했는데 추가적으로 더 더해질때 일어납니다. 예를들어 0xFFFFFFFF 에 0x00000001 을 더하면 발생합니다. 나머지는 잘 이해하셨습니다!
- 0
- 4
- 145
질문&답변
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
- 557
질문&답변
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
- 145
질문&답변
2020.04.26
메모리공간의 주소?
그럴리가요.. ㅎㅎ 저도 만들어주신 강의보고 배운게 많았어요. 아직 저는 학생 신분이라서 정식(?) 도우미는 조금 부담스럽지만 5월 중순부터는 시간적 여유가 생길 것 같아요. 시험 끝나면 메일 드릴께요.
- 4
- 4
- 1.6K
질문&답변
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
- 185
질문&답변
2020.04.25
메모리공간의 주소?
"일반적"으로 1바이트가 메모리를 읽는(접근 가능한) 단위이기에 그렇습니다. (옛날옛적에 4비트 단위로 사용하는 컴퓨터도 있었답니다. 보진 못했지만) 현대 운영체제에서는 실제로 메모리 공간을 RAM, SSD, HDD 어디에서든 할당 가능하며, 사용자가 사용하기 편하게 숫자 (주소값) 을 가상적으로 운영체제가 부여한 것 뿐입니다. 만약 1비트씩 메모리를 읽는다고 하면 메모리 크기만큼 메모리 주소 공간을 표현해야 하기 때문에 메모리 주소 표현에만 메모리를 거의 다 써버리게 됩니다... 그래서 메모리를 1바이트 단위로 나눠서 사용하는 것입니다. (예를들어 주소값으로 표현하면 0x00000001 와 0x00000002 는 1바이트 (8비트) 만큼 간격이 떨어져 있습니다.) 극단적인 예로 4비트 메모리를 사서 메모리를 1비트 단위로 사용하는 운영체제를 직접 만든다고 해봅시다. (4비트로는 이진수 0000 ~ 1111 까지 표현할 수 있으므로 십진수로는 0~15 를 표현 가능합니다.) 그런데 1비트씩 주소를 할당한다면 우리가 메모리를 모두 활용하기 위해서는 주소가 4개 (0x0 , 0x1, 0x2, 0x3) 나 필요한 것을 알 수 있습니다. 주소 4개를 표현하기 위해서는 최소 몇비트(이진수 몇자리)가 필요하죠? 네 맞습니다 2비트가 필요합니다 (이진수로 00, 01, 10, 11) 에고 주소 표현에만 벌써 2비트를 써버렸네요.. 메모리의 주소를 하나만 저장해도 메모리의 "절반"을 사용하지 못하게 되어버립니다. (돈을 많이 벌어서 8비트 메모리로 업그레이드 해도 여전히 주소 하나를 저장하는데 전체 메모리의 거의 "절반" 을 써야 합니다. ㅜㅜ) 이건 옛날에 컴퓨터를 만든 사람이 1바이트를 기준으로 메모리를 만들었고, 잘 팔렸기 때문입니다... 라고 설명하면 너무 날로먹는 설명인 것 같아서 좀더 자세히 설명드리자면. 숫자와 영문자를 저장하기 위한 코드표 "아스키 테이블"을 아실 겁니다. 옛날에는 지금처럼 이미지, 동영상, 음악등을 감상하기보다는 그냥 텍스트를 출력하거나 숫자를 연산하는게 주된 컴퓨터의 업무였습니다. 8바이트면 숫자, 특수문자, 영어 알파벳을 충분히 표현하고 남기에 8비트로 표준을 정한 것입니다. 정확히 말하자면, ISO 라는 기관에서 정한 국제표준 "ISO/IEC 80000" 입니다. (국제표준인데 안따르면 국제적으로 왕따당하겠죠..?) + 노파심에 말씀드리면, 메모리 접근 단위(크기)는 단순 운영체제를 만들때만 결정되는 문제는 아닙니다.. CPU, RAM, 보조기억장치 등 여러 장치에서 이미 8비트를 기준으로 아키텍쳐(설계) 를 만듭니다. 따라서 이러한 CPU, RAM 등을 효율적으로 사용하기 위해서라도 8비트를 기준으로 메모리를 엑세스 할 수 있게 OS 를 만든 것이라고도 보시면 되겠습니다.
- 4
- 4
- 1.6K
질문&답변
2020.04.24
2:27초 s_gets 함수에 대헤서 질문드립니다..
s_gets, gets 함수는 사실 C언어 표준 라이브러리에 이미 구현된 함수들이에요. 아마 사용되지 않더라도 원래 기능을 비슷하게 구현하기 위해서 반환을 만드신 것 같습니다. 참고 - https://en.cppreference.com/w/c/io/gets 추가로 gets 랑 친구격인 fgets 에서는 파일의 끝을 만났을때 fgets가 오류의 의미인 NULL을 반환하므로 오류가 발생하면 반복을 중단하고 파일을 더이상 읽지 않도록 만들수도 있는 등 유용하게 사용할 수도 있습니다.
- 0
- 2
- 185
질문&답변
2020.04.14
군인입니다
강의 초반에 온라인 IDE 몇가지가 소개되어 있습니다. https://lmgtfy.com/?q=online+ide
- 0
- 3
- 286