31 Ocak 2018 Çarşamba

std::index_sequence_for

Giriş
std::tuple, std::array gibi dizilerdeki elemanları açarak teker teker parametre olarak başka bir metoda sokmak için kullanılır.

Örnek
Elimizde şöyle bir metod olsun.
void printNumber(const int& x, const int& y)
{
  std::cout << "ONE" << std::endl;
}
Bu metodu çağıran şöyle bir kod olsun.
template<typename... TTuple, std::size_t... Indices>
auto apply_sequence(const std::tuple<TTuple...>& tuple, std::index_sequence<Indices...>)
{
  return printNumber(std::get<Indices>(tuple)...);
}

template<typename... TTuple>
auto apply_tuple(const std::tuple<TTuple...>& tuple)
{
  return apply_sequence(tuple, std::index_sequence_for<TTuple...>());
}
Çağırmak için şöyle yaparız.
std::tuple<int, int> one { 1, 2 };
apply_tuple(one); // ONE

valgrind leak-check aracı

Giriş
valgrind yerine mcheck aracını kullanmak daha kolay olabilir.

gdb
memcheck ile gdb'yi beraber kullanmak için şöyle yaparız.
valgrind --vgdb=yes --vgdb-error=0 app
leak-check
Şöyledir.
--leak-check=<no|summary|yes|full> [default: summary]
Bu aracın çıktısında iki tane başlık var
1. Heap Summary
2. Leak Summary
Her ikisine de bakmak gerekir.

leak-check= full
leak-check = full ise diğer seçenekler devreye girer. Açıklaması şöyle.
Once this option is set, you can use several other options to specify which kinds of memory leaks you want detailed reports for:

--show-leak-kinds=definite,possible only reports unfreed blocks with no pointers or that depend on interior pointers (the default)
--show-possibly-lost=no or --show-leak-kinds=definite only reports unfreed blocks with no pointers
--show-reachable=yes or --show-leak-kinds=all reports all forms of unfreed blocks, even trivial ones with clear pointers
show_leak_kinds seçeneği
leak-check = full ile etkindir. definite,indirect,possible,reachable,all,none seçeneklerinden birisini alır. Şöyle yaparız.

1.show-leak-kinds = definite, possible seçeneği - sadece kaybolan pointer'lar
Şöyle yaparız.
$ valgrind --leak-check=full -v ./a.out 
Şöyle yaparız.
$ valgrind --leak-check=full ./leak
Örnek
Definitely lost hatası yoksa çıktı olarak şuna benzer bir şey alırız.
==9145== HEAP SUMMARY:
==9145==     in use at exit: 64 bytes in 2 blocks
==9145==   total heap usage: 8 allocs, 6 frees, 300 bytes allocated
==9145== 
...
==9145== LEAK SUMMARY:
==9145==    definitely lost: 0 bytes in 0 blocks
==9145==    indirectly lost: 0 bytes in 0 blocks
==9145==      possibly lost: 0 bytes in 0 blocks
==9145==    still reachable: 64 bytes in 2 blocks
==9145==         suppressed: 0 bytes in 0 blocks
...
==9145== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==9145== 
==9145== 1 errors in context 1 of 1:
==9145== Syscall param rt_sigaction(act->sa_mask) points to uninitialised byte(s)
==9145==    at 0x4E6D3F1: __libc_sigaction (sigaction.c:62)
==9145==    by 0x401061: main (in /home/dac/ClionProjects/openshell/a.out)
==9145==  Address 0xffeffefc8 is on thread 1's stack
==9145== 
Örnek
Definitely lost hatası varsa çıktı olarak şuna benzer bir şey alırız. Hatanın yerini de gösterilir. Hata malloc()'lanan belleğin silinmemesidir.
==32091== HEAP SUMMARY:
==32091==     in use at exit: 1 bytes in 1 blocks
==32091==   total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==32091==
==32091== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==32091==    at 0x4C29110: malloc (in /usr/lib64/....)
==32091==    by 0x40056A: f (leak.c:1)
==32091==    by 0x40057A: main (leak.c:2)
==32091==
==32091== LEAK SUMMARY:
==32091==    definitely lost: 1 bytes in 1 blocks
==32091==    indirectly lost: 0 bytes in 0 blocks
==32091==      possibly lost: 0 bytes in 0 blocks
==32091==    still reachable: 0 bytes in 0 blocks
==32091==         suppressed: 0 bytes in 0 blocks
==32091==
Örnek
Elimizde şöyle bir kod olsun.
A a = *getA();
Şuna benzer bir şey alırız. Bu sefer hata new()'lenen belleğin silinmemesidir.
==13832== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==13832==    at 0x4C2D25F: operator new(unsigned long) (in /usr/lib/valgrind/...)
==13832==    by 0x108AAC: getA() (48538032.cpp:18)
==13832==    by 0x108AD4: doSomething() (48538032.cpp:22)
==13832==    by 0x108B3B: main (48538032.cpp:27)

2. show-leak-kinds= all seçeneği - herşey
Şöyle yaparız.
valgrind --leak-check=full --show-leak-kinds=all <prog_name>
Çıktı olarak şuna benzer bir şey alırız.
$cat main.cpp
int main(){}
$g++ -std=c++1z -o main main.cpp                         
$valgrind --leak-check=full --show-leak-kinds=all ./main
==26823== Memcheck, a memory error detector
==26823== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==26823== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==26823== Command: ./main
==26823== 
==26823== 
==26823== HEAP SUMMARY:
==26823==     in use at exit: 72,704 bytes in 1 blocks
==26823==   total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
==26823== 
==26823== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==26823==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/...
==26823==    by 0x4E9D62F: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==26823==    by 0x4010109: call_init.part.0 (dl-init.c:78)
==26823==    by 0x40101F2: call_init (dl-init.c:36)
==26823==    by 0x40101F2: _dl_init (dl-init.c:126)
==26823==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==26823== 
==26823== LEAK SUMMARY:
==26823==    definitely lost: 0 bytes in 0 blocks
==26823==    indirectly lost: 0 bytes in 0 blocks
==26823==      possibly lost: 0 bytes in 0 blocks
==26823==    still reachable: 72,704 bytes in 1 blocks
==26823==         suppressed: 0 bytes in 0 blocks
==26823== 
==26823== For counts of detected and suppressed errors, rerun with: -v
==26823== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)





std::iterator_traits

Giriş
STL algoritmalarında iterator tipleri çok kullanıılır. iterator_traits iterator'ler ile çalışmayı kolaylaştırır.
iterator_category Alanı
Örnek
Şöyle yaparız.
template <typename It>
std::string cat(It const&) {
  return typeid(typename std::iterator_traits<It>::iterator_category).name();
}
value_type Alanı
Bir iterator'ın value_type tipini
typename std::iterator_traits<Iterator>::value_type 
şeklinde alabilmemizi  sağlar.
Örnek
Şöyle yaparız.
std::iterator_traits<int*>::value_type
Örnek
Şöyle yaparız
#include <iterator>

template<typename Iterator>
typename std::iterator_traits<Iterator>::value_type 
sum(Iterator begin, Iterator end )
{
  using value_type = typename std::iterator_traits<Iterator>::value_type;
  value_type s = value_type();
  for (Iterator it = begin; it != end; it++) {
    s += *it;
  }
  return s;
}
Bir başka örnek'te benzer bir kullanım görülebilir.

Diğer
Aslında iterator_traits belirtilen iterator içindeki value_type'ı döndürmekten başka bir şey yapmaz. Yani şöyle de kodlayabilirdik.
template <typename Iter> auto func(Iter &first, Iter &last)
{
    using IterType = typename Iter::value_type;
    ...
}