본문 바로가기

C++

(50)
fsanitize 컴파일 옵션 [1. 개요]c++ 애플리케이션의 다양한 오류를 런타임에 찾고 수정하기 위한 한가지 방법이다.컴파일 시 해당 옵션을 지정하면, 컴파일러가 프로그램에 검사 코드를 자동 삽입하여 오류를 찾는데 도움을 준다. 다양한 옵션을 살펴보면 아래와 같다.-fsanitize=address버퍼 오버플로우, use-after-free 등 메모리 오류 탐지-fsanitize=undefined정의되지 않은 동작 (나눗셈 0, 정수 오버플로우 등)-fsanitize=leak메모리 누수 추적-fsanitize=memory초기화되지 않은 메모리 사용 (GCC 지원 안함.?)-fsanitize=threadrace condition 탐지-fsanitize=pointer-compare잘못된 포인터 비교/연산 감지-fsanitize=poi..
buffer overflow 사례1 [1. 개요]버퍼 오버플로우를 유발 할 수 있는 사례들을 정리한다. 포인터를 전달할 때, 실제 메모리는 해당 포인터 타입에 해당하는 크기만큼의 공간이 할당되어 있어야 한다.아래와 같은 타입 캐스팅은 가급적 하지 않는 것이 좋다.int value = 0x1234;long long *ptr = reinterpret_cast(&value);왜 그런가, ptr 을 대상으로 발생하는 연산은 ptr 이 가리키는 공간이 8byte 만큼 할당되어 있다고 판단하고연산을 진행한다.그러나, 실제 메모리 공간은 4바이트 이므로 할당된 메모리 공간을 넘어서는 문제가 발생할 수 있다. 아래 코드를 보면, func() 에는 변수 a 의 주소만 넘기는데, b 의 값이 변경되어 버린다.#include void func(unsigned..
Segmentation fault 사례5 [1. 개요]strncpy 사용 시, 버퍼 오버플로우 발생.정확히는, strncpy 사용 시 마지막 3번째 인자의 계산 오류로 인해 발생한 문제임. 아래와 같은 코드의 문제점은?#include #include #define max(a, b) ((a) > (b) ? (a) : (b))int main(){ char buf[512]; char buf2[512]; strcpy(buf2, "hello"); strncpy(buf, buf2, max(static_cast(strlen(buf2)) - strlen("helloworld"), 0)); std::cout 바로, int 와 size_t 간 자료형의 연산이다.size_t 는 64bit 프로그램에서..
std::enable_shared_from_this [1. 개요]std::enable_shared_from_this 를 상속한 클래스 (여기서 템플릿 T는 상속한 클래스를 말함) 는멤버 함수 내에서 shared_from_this() 를 호출하여 자기 자신에 대한 shared_ptr 을 생성 할 수 있다. 이것이 주로 활용되는 시점은 다음과 같다.콜백에서 자기 자신을 공유해야 할 때 (재참조 할 때)자기 자신을 다른 shared_ptr 구조로 넘겨야 할 때기타...shared_ptr 을 공유한다는 의미는 아래와 같다.실제 객체는 하나임그러나 여러 곳에서 참조하게 됨그래서 더 이상 참조하는 곳이 없어지게 되면 해당 객체는 자동 소멸하게 됨.그래서, 콜백에서 자기 자신을 공유해야 한다는 것은 아래와 같은 의미가 있다.일반적으로 콜백이라 함 은 특정 이벤트 발..
Placement new [1. 개요]placement new 라는 문법(혹은 기능) 은 일반적인 동적 할당 보다 조금 더 세밀하게 메모리의 수명을 관리할 수 있게 해준다. 일반적으로 객체를 대상으로 하는 new 는 메모리 할당 및 생성자 호출을delete 는 소멸자 호출 및 메모리 해제를 같이 진행 하게 해준다. 그러나, 아래와 같은 요구사항이 있을 수 있다.메모리를 할당만 하고, 생성자 호출은 뒤로 미루고 싶다.소멸자를 호출하여, 객체 내부의 메모리를 정리하지만, 객체 자체의 메모리는 당장 해제하지 않고 싶다.특히, 아래와 같은 상황도 있을 수 있다.공유 메모리를 대상으로 특정 객체를 공유하고 싶다.즉, 메모리는 이미 할당이 되어있지만, 객체의 생성자를 호출하고 싶다. 주의할 점은 소멸자가 자동으로 호출되지 않는다. (소멸자..
wchar_t 사용에 관하여 [2] [1. 개요]멀티바이트 문자열에서 wide char 문자열로 변환 혹은 그 반대 방향으로 변환 시 주의 점.Locale 에 대한 이해인코딩 변경이므로, 데이터 인코딩이 적절한지 확인출력에 관하여.[2. Locale 에 대한 이해]리눅스 기준으로는locale -a 를 이용하여, 현재 시스템에 설치된 locale 을 확인 할 수 있다.# locale-gen ko_KR.UTF-8 을 이용해서 한국어 관련 locale 을 설치 할 수 있다.윈도우에서 파워 쉘 기준으로는Get-WinSystemLocale 명령어로 확인 가능[3. 리눅스 관련 코드]#include #include #include #include #include int main(){ wchar_t wstr[128]; std:..
wchar_t 사용과 관련하여. [1. 개요]윈도우 환경에서 wchar_t 에 관련 된 여러 연산 들 중, 아래와 같은 연산 결과가 예상과 다름.iswdigitiswalphaiswalnum한글 '안' 을 유니코드로 표현하면, 10진수로 50504 이며,이는 기존 아스키 코드로 표현가능한 숫자, 영문이 아님을 알 수 있지만, 위 함수들의 결과는 숫자, 알파벳이라고 그 결과를 반환한다. 또, wstring 에 대해서, std::wcout 등을 통해 출력해도 정상적으로 문자열이 출력되지 않았음. 해결 방법을 알아보던 중, locale 을 제대로 설정하지 않았다는 것을 보았고, 그 밖에 관련된 것들이 아래와 같은데,std::locale() SetConsoleOutputCP(CP_UTF8);std::locale::global(std::local..
std::thread vs std::async
std::packaged_task [1. 개요]std::packaged_task는 C++11부터 도입된 기능으로, 함수나 함수 객체를 비동기적으로 실행시키고, 그 결과를 std::future를 통해 받아올 수 있도록 감싸주는 wrapper. 기본적으로 std::thread 로 실행 한 task 의 리턴 값을 받기 위한 별다른 메커니즘이 없다.std::promise 를 사용하는 것도 한가지 방법이기는 하지만,,,그러나, std::async 와 마찬가지로 task 의 리턴 값을 받기 위한 메커니즘을 제공한다는 측면이 있다.std::async 는 join() 을 따로 호출하지 않아도 되지만,std::thread 를 통해 호출하게 하므로, join() 의 호출은 필요 함.[2. 예제]가장 일반적인 사용 방법std::packaged_task 를 ..
std::bind [1. 개요]socket api 의 bind() 가 아니라, c++ 의 std::bind() 는 함수에 인자등을 미리 고정해서 함수 객체(callable) 를 만든다.아래와 같은 상황에서 주로 사용하는데,callback 을 등록 할 때,함수 객체 호출 시, 일부 인자를 미리 고정하고 싶을 때,다른 함수 객체들과 조합할 때,최신 C++ 에서는 lambda 식을 주로 사용하긴 하지만, 알아 둘 필요 있음.[2. 사용 방법 - 전역 함수]#include #include using namespace std;int add(int a, int b) { return a + b;}int main() { // add의 첫 번째 인자 10을 고정하고, 두 번째 인자는 나중에 받음 auto add10 = s..