본문 바로가기

C++

(41)
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..
bitfield 사용 시 유의할 점 [1. 개요]메모리를 bit 단위로 제어할 필요가 있을 때 사용하는 bitfield 에 대해서 사용 시 유의할 점.bitfield 멤버에 대해서 주소를 확인 할 수 없다. (주소연산 불가)비트 필드가 저장되는 순서 (MSB→LSB 등)는 플랫폼/컴파일러 의존적[2. 비트 필드가 저장되는 순서]Little-endian arch 에 g++ 컴파일러 기준으로 아래 예제를 실행하면,#include #include struct Mystruct { unsigned char a : 4; unsigned char b : 4;};int main(){ unsigned char c = 0x8f; Mystruct obj; memcpy(&obj, &c, sizeof(c)); std::cout 출..
std::stringstream [1. 개요] [2. 주의 사항]초기화 명목으로 보통 명명되는 clear() 함수는 stringstream 에서는 의도한 대로 작동하지 않는다.내부 버퍼를 초기화하는 역할로 동작하지 않음.stream 에서 clear() 함수는 보통, flag 등을 초기화하는 역할을 하기 때문...# failbit / eofbit 등.따라서, 내부 버퍼를 초기화 하려면, 아래와 같이 빈 문자열을 설정하도록 해야한다..str("");
OS 별 select() 함수 사용법 [1. 개요]select() 함수는 비동기 I/O 처리를 위한 시스템 콜이다.여러개의 파일 디스크립터(보통 소켓) 을 동시에 감시하면서, read/write/error 등의 상태를 체크한다. 함수 원형은 아래와 같다.int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); timeval 구조체의 내용을 채워, I/O 상태 변화를 timeout 동안 기다리고,NULL 이면, blocking 으로 동작하고,NULL 이 아니지만 0으로 채워져 있으면, non-blocking 으로 동작한다.[2. 주의점]위 함수 사용 시 주의할 점은 첫번째 파라미터이다.리눅스 커널에서는, readfds ,..
구조체 대입 연산 [1. 개요]구조체 간 대입 연산 시 생각 해 볼 만한 부분?별도로 복사 생성자나 대입 연산자 등을 구현하지 않으면, 컴파일러가 디폴트로 제공하는 것을 사용하게 되는데 멤버의 고정 길이를 갖는 배열이 있다면?Q) 얕은 복사가 발생하지 않나?A) 배열의 이름은 배열의 시작 주소를 포현하는 포인터이지만, 배열의 이름은 수정 할 수 없는 값이다. 따라서, 컴파일러는 고정 길이의 배열을 대상으로 깊은 복사를 하도록 디폴트 메소드를 제공한다. 어떻게 구현할지는 컴파일러 마다 다를 수 있음. (단, 배열은 그 크기를 아므로 memcpy 를 통해서 할 수 도 있다...)[2. 예제]#include #include struct Mystruct { int A; int B; ..
Segmentation fault 사례4 [1. 개요]보통 배열에 대한 for 문은 0 ~ n 까지 증가하는 방식으로 작성하는 경우가 많은데,반대로, n ~ 0 까지 감소하는 경우로도 (역 방향) 작성 할 수 있다. 이때, 실수 할 만한 부분은 아래와 같은 반복문이다.for (unsigned int idx=n-1; idx >= 0; idx--) { // something. // access arr[idx]} 문제는 변수 idx 의 자료형이 unsigned 라는 것이다.idx == 0 인 경우 배열 접근이 가능하나, 여기서 -1 을 하는 순간 -1 을 unsigned 로 해석하여 매우 큰 수가 되어 버린다.0xffffffff그래서, idx 가 0 보다 작아지는 경우는 절대 발생 할 수 없고, 매우 큰 번지 수를 참조하려는 비정상 상황이..
Segmentation fault 사례3 [1. 개요]힙 메모리 관련 하여, SIGSEGV 시그널 발생 사례 중...free(): invalid pointer 오류 발생하는 경우가 있음. 구체적인 상황은new[] 를 이용하여, 동적 길이의 배열을 생성해당 배열을 사용delete[] 를 이용하여 리소스 해제 => 이 때 오류가 발생하는데...문제는 gdb 를 통해서 delete[] 한 메모리 주소가 오염되었는지 확인해보았는데,최초 할당 시, 받은 주소였고,심지어, 해당 메모리에 접근하여 배열 내 값도 정상적으로 확인 할 수 있었음.즉, 아래와 같은 상황은 아니라는 것이다.double free 를 시도한다 던가...new[] 로 할당한 메모리를 단순히 delete 로 해제한다 던가...[2. 원인]위 상황에 대한 원인은 다른 힙 메모리에 발생한 o..
Segmentation fault 사례2 [1. 개요]아래 세그멘테이션 폴트 사례는 오염 된 포인터 변수에 접근 시 발생함.엄밀하게 말하면 스택 오버플로우가 아니기 때문임.[2. 예제]#include #define MAX_LEN 5struct A { int arr[MAX_LEN]; int len;};class MyContainer {private: // 메모리 배치를 고려하면... A first; const int *bptr; const char *cptr; const float *dptr;public: MyContainer() { first.len = 0; bptr = new int[MAX_LEN]; cptr = new char[MAX_LEN]; dp..
gdb 사용 방법 (기초) [1. 개요]리눅스 C++ application 디버깅 시, 유용한 툴 인 gdb 의 기초적인 사용 방법을 정리한다. 기본적으로 breakpoint 를 걸고, 한줄 단위로 실행해보기 위해서 디버깅 심볼들이 필요하다.따라서, CMake 기준에서는최적화를 많이 하는 Release 빌드 보다는 Debug 빌드가 적합하다.아래와 같이, gdb 실행 시 심볼들을 찾을 수 없다는 메시지가 출력 된다. g++ 로 직접 빌드하는 경우라면, -g 옵션을 사용하고, 최적화는 하지 않도록 한다.[2. 기본적인 실행] 1 #include 2 3 int sum(const int a, const int b) 4 { 5 const int aa = a*a; 6 ..
erase 계열 함수... [1. 개요]STL 컬렉션 들의 멤버 함수 erase() 의 리턴 값의 의미하는 바가 무엇인가?erase 의 입력으로 사용 된, 반복자의 다음위치를 가리키는 iterator 가 반환된다.[2. 예제]#include #include #include #include #include std::vector vec;std::list lst;std::map kv;std::unordered_set uos;void print_vec(){ std::cout "; auto itr1 = vec.erase(itr0); std::cout "; auto itr1 = lst.erase(itr0); std::cout first second "; auto itr1 = kv.erase(itr0); ..