# C++ Tips n Tricks C_INCLUDE_PATH - for C header files CPLUS_INCLUDE_PATH - for C++ header files - seperated by ":"(PathSeperator) LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib" PATH - to print the paths seen by compiler run the compiler with -v - -l should be after the file thats using it else you get undefined reference `g++ -ggdb VideoCaptureTest.cpp -lopencv_videoio -o VideoCaptureTest` - -Wl,--allow-shlib-undefined: ignores undefined symbols error in shared libraries ## print include paths g++ -E -x c++ - -v < /dev/null ## list symbols in library nm -gDC yourLib.so ## to print linker path, ld refers LD_LIBRARY_PATH only for indirect deps ld --verbose ``` valgrind --leak-check=full --show-leak-kinds=all \ dist/Debug/GNU-Linux-x86/ferrymediaserver -t 100 -s normal //checks for unused variables, null pointer dreferencing, uninitialized //variables clang-tidy test.cpp -checks=-*,clang-analyzer-*,-clang-analyzer-cplusplus* ``` Sure, find where -Werror is set and remove that flag. Then warnings will be only warnings. Thanks Daniel, but there is no -Werror flag set in my project. Should I look for it somewhere else ? Somewhere it must be set, by default warnings aren't treated as errors by any compiler I know. If you can't find it, you can try overriding it with -Wno-error, as nightcracker suggested. That should work unless the -Werror is passed after the flags you set in CFLAGS in the makefile. – Daniel Fischer Jul 19 '12 at 12:59 - `-Wno-changes-meaning` treats `changes-meaning` as warning and not an error. ## make `make CFLAGS="-DCASE_SAFE -ggdb -O0"` // includes header from current directory overriding standard header #include_next "stdio.h" // include header from implementation defined places #include // include source from current directory and then implementation defined places #include "stdio.c" ## check for debug symbols ``` objdump --debugging /usr/lib/libc.so readelf --debug-dump=decodedline /usr/lib/libc.so #prefer this ``` ELF - Executable and Linkable Format ## find the options or debug options with which the file is built with ` strings foo.o | grep -- -O #or readelf --debug-dump=info foo[,.o,.so] | grep "DW_AT_producer" ` ## llvm - CFG: Call Flow Graph `LLVM ERROR: failed to annotate CFG` - llvm stands for Low Level abstraction layer that converts language frontend to target assembly. It converts language frontend to ITR on which it applies all the optimizations ## Cmake ``` cd Build/Linux/x86_64/Debug/ // to print all configurable variables cmake -L .. CC=gcc CXX=g++ cmake -G "Unix Makefiles" -DBUILD_TESTING=1 -D_DEBUG=1\ -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_EXPORT_COMPILE_COMMANDS=1 --build\ ../../../../ rdm& # for emacs rtags or brew services restart rtags # on macOS rc -J # for emacs rtags cmake -D_DEBUG=1 -G "visual studio" -A x64 -DCMAKE_CXX_FLAGS="-g -O0" ../FFJSON -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_CONFIGURATION_TYPES="Release;Debug" ``` ## CPP vs CXX - CPP refers to C and C++ Preprocessor. CXX refers to C++ # Rice ``` gcc -march=native -mcpu=native -mtune=native -Q --help=target -v - gcc --help=optimizers cpuid2cpuflags echo "*/* $(cpuid2cpuflags)" > /etc/portage/package.use/00cpu-flags ``` ## gdb ``` gdb --args ./myapp -a some_arg_value cd workDirectory start run step - or - s - steps in to a function stepi - steps in to next machine instruction next - or - n - steps over to a funtion continue - or - c - continues till program end or next break point finish - fin - continue to the end of current function; nearly equal to stepout break : - set breakpoint b : if this=0x12345678 - conditional break info break - list breakpoints del dis en ignore print p/x - print in hex; d-decimal o-octal t-binary p {var1,var2,var3} - print multiple vars display - print at every step call info register edi info locals -prints all variables backtrace - or - bt - prints callstack set environment variablename [=value] set breakpoint pending on save breakpoints source #this is a comment inside breakpoints file watch var cond var>=value watch *(unsigned long *)0x555555679b70 -breaks on modified memory location awatch *0x555555679b70 -breaks on accessing memory location info breakpoints; dis -to disable watchpoint set logging file set logging on set disable-randomization off set verbose on set print elements 0 #prints full line handle SIGILL nostop signal 2 #sends interrupt signal from gdb f[rame] - print current line of execution f - jump to a function in stack up 200 - brings u up 200 frames where - print detailed current line of execution info proc mappings 0x555555554000 0x555555590000 0x3c000 0x0 r--p /mnt/ssd2/openssl/install/bin/openssl 0x555555662000 0x5555556a6000 0x44000 0x0 rw-p [heap] find 0x555555554000, 0x5555556a5999, "Hello, world" ``` ### analyze coredumps - `gdb ./example core` ## gdbserver `ps aux | grep mainboard | grep planning` #Necktwi 13962 16.8 2.1 8137764 685096 pts/3 Sl 13:57 32:20 mainboard -d /apollo/modules/planning/dag/planning.dag `gdbserver :1111 --attach 13962` #Attached; pid = 13962 #Listening on port 1111 #on client ``` gdb target remote [host]:port set remote interrupt-sequence Ctrl-c show remote interrupt-sequence ``` ### gdbserver start program from gdb client ``` cd projectRoot gdbserver --multi :1111 ``` #on client ``` gdb target extended-remote [host]:port #if necessary copy file that you want to debug to target machine remote put .cache/bazel/540135163923dd7d5820f3ee4b306b32/execroot/apollo/bazel-out/k8-dbg/bin/cyber/mainboard/mainboard /apollo/bazel-bin/cyber/mainboard/mainboard set remote exec-file /apollo/bazel-bin/cyber/mainboard/mainboard -d /apollo/modules/planning/dag/planning.dag start run info inferiors ``` ## lldb ``` lldb -- ./FerryFair -s normal #> run #(r) starts n breaks at main next #(n) next line continue #(c) runs till end or breakpoint backtrace #(bt) prints callstack step #(s) steps into function thread step-inst #(si) instruction level step thread step-out #(finish(fin)) step out function breakpoint list #(br l) prints breakpoints ``` ## rtags ``` rdm & #in project folder with compile_comands.json do it only once rc -J . ``` ## bear - generate compile_commands.json for below cases ``` bear -- clang -v -ggdb0 -std=c++11 -L/opt/rocm/opencl/lib -lOpenCL \ -I/opt/rocm/opencl/include CasRSA_CL.c -o CasRSA_CL bear --append -- make -j6 ``` ## Bazel ## distcc ``` export DISTCC_VERBOSE=1 pump distcc gcc -c main.c -o main.o gcc main.o -o main configure.ac->autoconf->configure Makefile.am->automake->Makefile.in Makefile.in->configure->Makefile #configure.ac:2: error: possibly undefined macro: AM_INIT_AUTOMAKE autreconf -i ``` ## get libraries linked by an executable `ldd` ## list shared libraries to which the process is linked to `lsof -p ` ## linker ignore indirect dependency ``` g++ main.cpp -o main -I. -L. -lB \ -Wl,-unresolved-symbols=ignore-in-shared-libs ``` -E Stop after the preprcessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output. Input files that don't require preprocessing are ignored. -dD Dump all macro definitions, at the end of preprocessing, in addition to normal output. C:\Program Files\Age of Mythology\Language\en\en-language.txt Converting constructor ## Multiple definitions in GCC 10 but not in GCC 8 - variable definition without initialization is considered tentative and is not allowed as per C standard but many compilers allow it; gcc-10 does not. - use `-fcommon` to allow tentative definitions. ## Don't optimize ``` #pragma GCC push_options #pragma GCC optimize ("O0") #pragma GCC pop_options ``` ## Predefined macros on various platforms ### Windows _WIN32 Both 32 bit and 64 bit _WIN64 64 bit only ### Unix (Linux, *BSD, Mac OS X) unix __unix __unix__ ### Mac OS X __APPLE__ __MACH__ #Both are defined; checking for either should work. ### Linux __linux__ linux __linux ### FreeBSD __FreeBSD__ ## Enable overflow interrupts `-ftrapv` ## Parallel compilation (4 threads) `make -j4` ## const cast ``` int a = 5; int b = 6; const int* i = &a; i = &b // legal *i = 5 // illegal ``` ## inline functions - its only a suggestion to compiler, its not gauranteed; where as a macro function is guaranteed to be inline. ## Initialization of inherited fields of parent members ``` struct B : struct A { B (int i, int j) : A (i), j(j) {} } ``` ## smart pointers ### unique_ptr - deletes the held object when it goes out of scope or another object assigned to it. ### shared_ptr - deletes the held object when there is no other shared_ptr holding the object. ### convert unique to shared ``` std::unique_ptr up = std::make_unique(); std::shared_ptr sp = std::move(up); ``` - shared to unique not allowed ## lambda function'/home/Necktwi/workspace/Wavelabs/tritonmo ``` struct S2 { void f(int i); }; void S2::f(int i) { [=]{}; // OK: by-copy capture all external varibles by default [=, &i]{}; // OK: by-copy capture, except i is captured by // reference [=, *this]{}; // until C++17: Error: invalid syntax // since c++17: OK: captures the enclosing S2 by // copy [=, this] {}; // until C++20: Error: this when = is the default [&]{}; // OK: by-reference capture default [&, i]{}; // OK: by-reference capture, except i is captured // by copy [&, &i] {}; // Error: by-reference capture when by-reference // is the default [&, this] {}; // OK, equivalent to [&] [&, this, i]{}; // OK, equivalent to [&, i] [capture clause](parameters) -> return-type {definition} } ``` ## deleted function `MyClass_ (const MyClass_& myclass) = delete;` will prevent object from being copied. ## variadic arguments arguments like arguments to printf are called variadic arguments. they are declared with ellipsis operator(...) ```C++ va_list ptr; va_start(ptr, argCount); for (int i=0; i var = va_arg(ptr, ); va_end(ptr); ``` ## mutex - waiting threads sleep - can be implemented with interrupts - implemented with atomics ## spin locks - waiting threads don't sleep - uses atomic - peterson's algorithm ## atomic operation - on single threaded processor its an uninterruptible codeblock. - on multi threaded processor no other thread can enter the block while its being executed. ## semaphores - can be used to allow only number of cores number of processes to run. ## conditional variable ``` #include pthread_cond_t myConVar = PTHREAD_COND_INITIALIZER; pthread_mutex_t mymutex; pthread_cond_wait(&myConVar , &mymutex); pthread_cond_signal(&myConVar); // unblocks one of the waiting threads pthread_cond_broadcast(&myConVar); ``` ## Interview Questions Q format specifiers - %lu - unsigned long - %lld - long long - %llu - unsigned long long - %04x - hex in small letters with print width 4 characters - %07X - hex in big letters with print width 7 characters - %lx - print long in hex - %d - bool(yes we got only to typecast to int) - %lf - double - %u - unsigned int - %zu - size_t - %ld - long - %.*s, 4, str - to print 4 chars of string - %3.4f - decimal length 3, fractional length 4 - %05d - length of 5 decimals - %p - pointer Q literal foramats - 0b01100011 binary literal - 0x9f hexa decimal literal - 0457 ocatal literal Q what are OOPS concepts or principles? - encapsulation, inheritance, polymorphism, abstraction, Association (Composition, Aggregation). Q What is runtime polymorphism and compile time polymorphism - method overloading is compile time and method overriding with virtual keyword is runtime. Q abstract class - class with atleast one pure virtual function `virtual int someFunc () = 0` - Interface is a set of abstract classes Q Static functions - Only visible within the file. static member functions have access to only static members. Q How to implement return type based function overloading? - You can't using templates but you may using functors(T1 operator()(T2, T3)). Q What is "pointer to incomplete class type is not allowed" error? - An incomplete class is one declared but not defined. Q increment a pointer or add interger - increments address by the size of datatype Q delete[] on non array pointer - results in undefined behavior as per C++ standard but gives memory leak by most compilers. Q What is diamond problem - Ambiguous members due to a common grand parent is the diamond problem. Remedy is virtual keyword - class Mummy_ : virtual public Person_{} //by default inheritance is - class Daddy_ : virtual public Person_{} //private - class Son_ : public Mummy_, public Daddy_ - Pitfall: Adds vptr to Son_ object Q std::map n std::unordered_map time complexities - Ordered = O(log(n)) - Unordered = O(1) - key->hashFunction->index->value. Q 0.3f + 0.0f takes long time than 0.3f + 0.2f - floating point gets denormalised because 0.0f binary reperesentation starts with 1.0 which complicates arthmetic operation on most processors - 1 - sign - 8 - exponent - 23 - fraction(need to add 1 as LSB) - so the number is sign*(fraction1)*2^(exponent-127) - all numbers <= 2^-127 are subnormals/denormals, they are computed as (-1)signbitx2^-126 x 0.fraction(not fraction1) - so the least non zero number is sign:0|exp:0|frac:1 = 1x2^-127 Q for loop unrolling - Compilers like opencl will divide the loop in to disjoint blocks and execute them in parallel. - llvm uses it to optimization Q Storage classes - used to describe the features of a variable/function. These features basically include the scope, visibility and life-time which help us to trace the existence of a particular variable during the runtime of a program. - auto - automatically derive data type - register - place the variable in register for rapid use - extern - global variable, initial value 0 - static - initial value 0, lifetime whole program - mutable - can be modified by const function Q Volatile members - No optimization by the compilers as they are inteneded to use by unknown external programs; hence volatile variable never stored in registers or cache, they are always fetched from the memory. Q linker option -fPIC -fPIE - Linker generates Position Independent Code/Executable: all the addresses are relative instead of absolute. PIC for shared objects while PIE for executables. Q right shift operator - fills 1 if its signed datatype else fills 0 if unsigned Q Why struct keyword in declaration? - It is used in forward declaration - It resolves ambiguity between same function and class names. - Its just a c standard. Q can there be virtual constructor - no Q can there be virtual destructor - yes. used to destruct derived class objects with base class pointer. Q when virtual function called from base class constructor which class function is invoked? - the function of the same class is invoked. and also destructor invokes the function of same class. - virtual keyword will be forwarded down to all levels of inheritance - To determine byte endianness, type cast int variable with value 1 to char variable, if the char variable is 1 then little endian else if 0 then big endian. - RAII - Resource Allocation IS Initialization ``` #include mutex m; void good() { lock_guard lk(m); f(); if(!everything_ok()) return; } ``` - initializer list is used to initiate non static const members, reference members, for initiation of member objects that doesn't have default constructor, parameterized constructor of the base class can only be called using the initializer list and performance is improved by not calling assignment operator. - uniform initialization: stricter type checking ``` class Base { char x; public: Base(char a) : x{a} {} void print() { std::cout << static_cast(x); } }; ``` - C++ memory layout 1. Text Segment 2. Data Segment 1. Initialized Data Segment - global and static 2. Uninitialized Data Segment - initialized to zero by kernel 3. Heap 4. Stack Q C++ typecasting static_cast C++ compiler already knows how to convert between scaler types such as float to int. Use static_cast for them. When you ask compiler to convert from type A to B, static_cast calls B's constructor passing A as param. Alternatively, A could have a conversion operator (i.e. A::operator B()). If B doesn't have such constructor, or A doesn't have a conversion operator, then you get compile time error. Cast from A* to B* always succeeds if A and B are in inheritance hierarchy (or void) otherwise you get compile error. Gotcha: If you cast base pointer to derived pointer but if actual object is not really derived type then you don't get error. You get bad pointer and very likely a segfault at runtime. Same goes for A& to B&. Gotcha: Cast from Derived to Base or viceversa creates new copy! For people coming from C#/Java, this can be a huge surprise because the result is basically a chopped off object created from Derived. dynamic_cast dynamic_cast uses runtime type information to figure out if cast is valid. For example, (Base*) to (Derived*) may fail if pointer is not actually of derived type. This means, dynamic_cast is very expensive compared to static_cast! For A* to B*, if cast is invalid then dynamic_cast will return nullptr. For A& to B& if cast is invalid then dynamic_cast will throw bad_cast exception. Unlike other casts, there is runtime overhead. const_cast While static_cast can do non-const to const it can't go other way around. The const_cast can do both ways. One example where this comes handy is iterating through some container like set which only returns its elements as const to make sure you don't change its key. However if your intent is to modify object's non-key members then it should be ok. You can use const_cast to remove constness. Another example is when you want to implement T& SomeClass::foo() as well as const T& SomeClass::foo() const. To avoid code duplication, you can apply const_cast to return value of one function from another. reinterpret_cast This basically says that take these bytes at this memory location and think of it as given object. For example, you can load 4 bytes of float to 4 bytes of int to see how bits in float looks like. Obviously, if data is not correct for the type, you may get segfault. There is no runtime overhead for this cast. C-style cast (type)value Function-style cast type(value) Q Precedence of Arithmetic operators () parentheses ^, *, /, % in the order left to right + - Q Copy constructor vs assignment operator - invokes contructor vs bitwise copy when not overloaded - called when new obj created vs ops on existing obj ## constexpr - executes function at compile time ``` constexpr int product(int x, int y) { return (x * y); } int main() { constexpr int x = product(10, 20); std::cout << x; return 0; } ``` ## CCache - clear cache `ccache -C` ## Standard or popular functions and classes ### std::equal - returns true if the two input ranges are exactly equal ### std::lock_guard - unlocks the mutex when lock_guard object is destroyed std::lock_guard lck(loader_mutex); ### std::recursive_mutex - same thread can acquire multiple locks ### std::optional - wraps uninitialized variables ``` std::optional somefunc(bool b) { if (b) return string("someString"); return std::nullopt; } ``` ## ABI - find ABI of an executable ``` /// return a heap allocated string describing the ABI of current executable //// I don't recommend using this const char*getmyabi(void) { char mycmdname[80]; int sz = snprintf(mycmdname, sizeof(mycmdname), "/usr/bin/file -L /proc/%d/exe", getpid()); assert (sz < (int) sizeof(mycmdname)); FILE*f = popen(mycmdname, "r"); if (!f) { perror(mycmdname); exit(EXIT_FAILURE); }; char* restr = NULL; size_t siz = 0; getline(&restr, &siz, f); if (pclose(f)) { perror("pclose"); exit(EXIT_FAILURE); }; return restr; } // end of getmyabi /// the code above in untested ``` ## C++ memory model features - sequential consistency - atomic operations - memory order ## memory layout of c programs - command line arguments and environment variables - high address - stack - heap - uninitialized data - initialized data - text - instructions - low addresss ## Graph - has nodes: {x,y,z} and edges: {pair(x,y), pair(y,z)} - Tree is a DirectedAcyclicGraph(DAG) - Graph is represented in one of the following ways - Edge Lists - [[0,1], [0,2], [0,3], [2,3]] - Adjacency Matrices - [[0, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0]] - O(n) = 1 - Adjacency lists - [[1, 2, 3], [0], [0], [0]] - O(n) = log(n) - Types of graphs - Undirected: social network - Directed: links between pages - Weighted: roads - Unweighted: social network - Complete: all nodes connected to each other; tournment: every player against other player - Bipartite: can b devided in to 2 sets, each node in a set connected to a node in other set; job applicants and job openings - Trees: DAG; family tree - Cycles: at least one cycle; roads - Sparse: few edges compared to nodes; chemical reactions where each edge is reaction between two compounds - Dense: many edges compared to nodes; social network - Spanning subgraph: a subgraph with same nodes but different edges ### BFS: Breadth First Search - 0-1-3 | | \2-4 1. v(visited): 0; q(queue): 1, 2 2. v: 0, 1; q: 2, 3 3. v: 0, 1, 2; q: 3, 4 4. v: 0, 1, 2, 3; q: 4 5. v: 0, 1, 2, 3, 4; q: ### DFS: Depth First Search 1. v: 0; s(stack): 1, 2 2. v: 0, 1; s: 3, 2 3. v: 0, 1, 3; s: 2 4. v: 0, 1, 3, 2; s: 4 5. v: 0, 1, 3, 2, 4; s: ## Queue - FIFO - linked list or array with front and back pointers - simple, circular, priority(heavy elements popped first), double ended ## Heap - MaxHeap: complete binary tree where a node's value is >= its children - MinHeap: opposite of MaxHeap - O(log n) - priority queus, sorting, finding the median, Dijkstra'a algorithm, network routing, huffman coding ## Hash table - implements associative array that stores key-value pairs. hash(key)=valueLocation. - common hash functions are modulo division, bitwise operations and polynomial hashing - collisions are resolved using - Open addressing: next available slot is determined using linear, quadratic, double hashing probing techniques - separate chaining: store key-value pairs in linked lists at each index, leading to better performance for larger data sets. ## Hardened Toolchain ### Source foritification - detects cretain classes of buffer overflows - enabled by -D_FORTIFY_SOURCE=[0,1,2,3] ### libstdc++ assertions - couldn't find any documents on it; supposedly it enables additional assertions - its enabled by -D_GLIBCXX_ASSERTIONS compiler macro ### Stack Smashing Protector (SSP) - enabled by -fstack-protector-strong option - it causes the compiler to insert a check for stack buffer overflows before function returns. It kills application immediately if check fails. - it arranges code so that stackoverflow is very likely to be detected by the application and aborts. - it is part of PaX(Kernel Security Patches by PaX team part of Gentoo) ## STL ### Algorithms #### Sorting - std::sort(first_iterator, last_iterator, greater()): quick sort by default, but if its doing unfair partitioning and taking more than N*logN time, it switches to HeapSort and when array size is small then InsertionSort - quick sort: 10, 80, 30, 90, 40 1 choose pivot(40), initiate barricade = index = 0 2 increment barricade till array element is > pivot, if barricade> index then index = barricade; barricade=1 index=1 3 increment index till next element is <= pivot: index=2 4 swap the index element with barricade - 10, 30, 80, 90, 40 5 goto 2 #### Searching - binary_search(firstIterator, lastIterator, x): tests whether x exists in sorted vector or not. #### reverse(firstIterator, lastIterator) - reverses a vector #### max_element(firstIterator, lastIterator) #### min_element(firstIterator, lastIterator) #### accumulate(firstIterator, lastIterator, initialValue) - does the summation of vector elements #### count(firstIterator, lastIterator, x) - count occurrences of x in vector #### find(firstIterator, lastIterator, x) - returns iterator to first occurance of x #### lower_bound(firstIterator, lastIterator, x) - returns first element that is >= x #### upper_bound(first_iterator, last_iterator, x) - returns first element that is > x ## templates ```C++ template T myMax(T x) { return (x > m) ? x : m; } int main () { cout << myMax(10) << endl; } ``` ## lvalue - has name and address ## rvalue - has only address ## RVO - Return Value Object is compiler optimization that eleminates copying return value. ## version features ### 11 - + operator for string `string text = "player "; text+=to_string(4);` - T::move(T&& obj) - std::move converts lvalue reference(&) to rvalue reference(&&); - forward - in vector - void push_back(const T& value); - void push_back(const T&& value); - multi-threading-aware memory model - fences: MSVC/ICC gives `__mm_lfence`, `mm_mfence` ### 20 - in vector - constexpr void push_back(const T& value); - constexpr void push_back(const T&& value); - format returns string ### 23 - println: based on format ## task scheduler ``` [A, B, "", A, B, "", A, B] t = ["A","A","A","B","B","B"] tt[100]; tasktypes[100]; ttsize=0; tt[0]=0; for (int i=1; i< t.size; ++i) { if(t[i]!=t[i-1]){ tt[ttsize]=i; tasktype[ttsize]=t[i]; ++ttsize; } } n=2 int i=0; int j=0; while (sizeof(tt)) { if (i%n=trgtdst) return } } i=0,dst:10,fulelvl:70,stpstn:[10] i=1,dst:60,fl:110, stpstn:[10,60] ```