Wednesday, March 13, 2019

Callback via C++ template

The following code would make a callback via template:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <iostream>


template <typename F>
void call(F func)
{
    func();
}


void print()
{
    std::cout << __FUNCTION__ << "()" << std::endl;
}

int main()
{
    call(print);
}

Sunday, March 10, 2019

Debugging Issues related to GLib

Got this problem when running my compiled wxformbuilder:


***MEMORY-ERROR***: wxformbuilder[19377]: GSlice: assertion failed: aligned_memory == (gpointer) addr
Aborted (core dumped)

The workaround is to embed G_SLICE=always-malloc when invoking the command-line, e.g:

G_SLICE=always-malloc ./wxformbuilder 

According to the GLib documentation:

always-malloc:This will cause all slices allocated through g_slice_alloc() and released by g_slice_free1() to be actually allocated via direct calls to g_malloc() and g_free(). This is most useful for memory checkers and similar programs that use Boehm GC alike algorithms to produce more accurate results. It can also be in conjunction with debugging features of the system's malloc() implementation such as glibc's MALLOC_CHECK_=2 to debug erroneous slice allocation code, although debug-blocks is usually a better suited debugging tool.

To debug the issue, valgrind is our friend in this case.

For example, when running it with valgrind it shows a lot of memory leaks (apparently some issues in wxWidgets):



valgrind ./wxformbuilder

==18887== Memcheck, a memory error detector

==18887== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==18887== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==18887== Command: ./wxformbuilder

==18887==

==18887== Invalid free() / delete / delete[] / realloc()
==18887== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==18887== by 0x6EAE3D0: wxLocale::GetSystemEncodingName() (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAEA2A: wxLocale::GetSystemEncoding() (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F06C18: wxCSConv::SetEncoding(wxFontEncoding) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D2E3: wxCSConv::wxCSConv(wxFontEncoding) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D398: wxGet_wxConvLocalPtr() (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6DD07CE: _GLOBAL__sub_I_strconv.cpp (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x4010732: call_init (dl-init.c:72)

==18887== by 0x4010732: _dl_init (dl-init.c:119)

==18887== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)

==18887== Address 0x4029fe0 is in a rwx anonymous segment

==18887==

==18887== Invalid read of size 16

==18887== at 0x7E8798D: __wcsnlen_sse4_1 (strlen.S:117)

==18887== by 0x7E74EC1: wcsrtombs (wcsrtombs.c:104)

==18887== by 0x6F8B13F: wxWC2MB(char*, wchar_t const*, unsigned long) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F07CD5: wxMBConv::FromWChar(char*, unsigned long, wchar_t const*, unsigned long) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F14F78: wxString::AsChar(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0C2F9: wxCSConv::DoCreate() const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D2EB: wxCSConv::wxCSConv(wxFontEncoding) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D398: wxGet_wxConvLocalPtr() (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6DD07CE: _GLOBAL__sub_I_strconv.cpp (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x4010732: call_init (dl-init.c:72)

==18887== by 0x4010732: _dl_init (dl-init.c:119)

==18887== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)

==18887== Address 0x14d47b30 is 8 bytes after a block of size 24 alloc'd

==18887== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==18887== by 0x6F07DB7: wxMBConv::FromWChar(char*, unsigned long, wchar_t const*, unsigned long) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F14F78: wxString::AsChar(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0C2F9: wxCSConv::DoCreate() const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D2EB: wxCSConv::wxCSConv(wxFontEncoding) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D398: wxGet_wxConvLocalPtr() (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6DD07CE: _GLOBAL__sub_I_strconv.cpp (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x4010732: call_init (dl-init.c:72)

==18887== by 0x4010732: _dl_init (dl-init.c:119)

==18887== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)

==18887==

==18887== Invalid read of size 16

==18887== at 0x7E87992: __wcsnlen_sse4_1 (strlen.S:117)

==18887== by 0x7E74EC1: wcsrtombs (wcsrtombs.c:104)

==18887== by 0x6F8B13F: wxWC2MB(char*, wchar_t const*, unsigned long) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F07CD5: wxMBConv::FromWChar(char*, unsigned long, wchar_t const*, unsigned long) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F14F78: wxString::AsChar(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0C2F9: wxCSConv::DoCreate() const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D2EB: wxCSConv::wxCSConv(wxFontEncoding) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D398: wxGet_wxConvLocalPtr() (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6DD07CE: _GLOBAL__sub_I_strconv.cpp (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x4010732: call_init (dl-init.c:72)

==18887== by 0x4010732: _dl_init (dl-init.c:119)

==18887== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)

==18887== Address 0x14d47b40 is 16 bytes after a block of size 32 in arena "client"

==18887==

==18887== Conditional jump or move depends on uninitialised value(s)

==18887== at 0x7E87A61: __wcsnlen_sse4_1 (strlen.S:161)

==18887== by 0x7E74EC1: wcsrtombs (wcsrtombs.c:104)

==18887== by 0x6F8B13F: wxWC2MB(char*, wchar_t const*, unsigned long) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F07CD5: wxMBConv::FromWChar(char*, unsigned long, wchar_t const*, unsigned long) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F14F78: wxString::AsChar(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0C2F9: wxCSConv::DoCreate() const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D2EB: wxCSConv::wxCSConv(wxFontEncoding) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F0D398: wxGet_wxConvLocalPtr() (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6DD07CE: _GLOBAL__sub_I_strconv.cpp (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x4010732: call_init (dl-init.c:72)

==18887== by 0x4010732: _dl_init (dl-init.c:119)

==18887== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)

==18887==

==18887== Invalid free() / delete / delete[] / realloc()

==18887== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==18887== by 0x6EAE3D0: wxLocale::GetSystemEncodingName() (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x629CE5E: wxApp::Initialize(int&, wchar_t**) (in /usr/local/lib/libwx_gtk3u_core-3.1.so.3.0.0)

==18887== by 0x6EABB9C: wxEntryStart(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5A9: wxInitialize(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5FA: wxEntry(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x1E8D57: main (maingui.cpp:83)

==18887== Address 0x4029fc0 is in a rwx anonymous segment

==18887==

==18887== Invalid read of size 16

==18887== at 0x7E87AC2: __wcsnlen_sse4_1 (strlen.S:194)

==18887== by 0x7E74EC1: wcsrtombs (wcsrtombs.c:104)

==18887== by 0x6F8B13F: wxWC2MB(char*, wchar_t const*, unsigned long) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F07CD5: wxMBConv::FromWChar(char*, unsigned long, wchar_t const*, unsigned long) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F14F78: wxString::AsChar(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6E763C4: wxString::AsCharBuf(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x7016906: wxSetEnv(wxString const&, wxString const&) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x629D359: wxApp::Initialize(int&, wchar_t**) (in /usr/local/lib/libwx_gtk3u_core-3.1.so.3.0.0)

==18887== by 0x6EABB9C: wxEntryStart(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5A9: wxInitialize(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5FA: wxEntry(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x1E8D57: main (maingui.cpp:83)

==18887== Address 0x14e00f20 is 0 bytes after a block of size 80 alloc'd

==18887== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==18887== by 0x6F07DB7: wxMBConv::FromWChar(char*, unsigned long, wchar_t const*, unsigned long) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F14F78: wxString::AsChar(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6E763C4: wxString::AsCharBuf(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x7016906: wxSetEnv(wxString const&, wxString const&) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x629D359: wxApp::Initialize(int&, wchar_t**) (in /usr/local/lib/libwx_gtk3u_core-3.1.so.3.0.0)

==18887== by 0x6EABB9C: wxEntryStart(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5A9: wxInitialize(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5FA: wxEntry(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x1E8D57: main (maingui.cpp:83)

==18887==

==18887== Invalid read of size 16

==18887== at 0x7E87AC7: __wcsnlen_sse4_1 (strlen.S:194)

==18887== by 0x7E74EC1: wcsrtombs (wcsrtombs.c:104)

==18887== by 0x6F8B13F: wxWC2MB(char*, wchar_t const*, unsigned long) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F07CD5: wxMBConv::FromWChar(char*, unsigned long, wchar_t const*, unsigned long) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F14F78: wxString::AsChar(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6E763C4: wxString::AsCharBuf(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x7016906: wxSetEnv(wxString const&, wxString const&) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x629D359: wxApp::Initialize(int&, wchar_t**) (in /usr/local/lib/libwx_gtk3u_core-3.1.so.3.0.0)

==18887== by 0x6EABB9C: wxEntryStart(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5A9: wxInitialize(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5FA: wxEntry(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x1E8D57: main (maingui.cpp:83)

==18887== Address 0x14e00f30 is 16 bytes after a block of size 80 alloc'd

==18887== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==18887== by 0x6F07DB7: wxMBConv::FromWChar(char*, unsigned long, wchar_t const*, unsigned long) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6F14F78: wxString::AsChar(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6E763C4: wxString::AsCharBuf(wxMBConv const&) const (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x7016906: wxSetEnv(wxString const&, wxString const&) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x629D359: wxApp::Initialize(int&, wchar_t**) (in /usr/local/lib/libwx_gtk3u_core-3.1.so.3.0.0)

==18887== by 0x6EABB9C: wxEntryStart(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5A9: wxInitialize(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x6EAC5FA: wxEntry(int&, wchar_t**) (in /usr/local/lib/libwx_baseu-3.1.so.3.0.0)

==18887== by 0x1E8D57: main (maingui.cpp:83)

==18887==

==18887== Invalid free() / delete / delete[] / realloc()

==18887== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==18887== by 0xA95DAFB: _XFreeDisplayStructure (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)

==18887== by 0xA94AE7E: XCloseDisplay (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)

==18887== by 0x12331FC8: atspi_get_a11y_bus (in /usr/lib/x86_64-linux-gnu/libatspi.so.0.0.1)

==18887== by 0xD2DEE89: atk_bridge_adaptor_init (in /usr/lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0.0.0)

==18887== by 0x85D3B03: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)

==18887== by 0x8774498: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)

==18887== by 0x915410C: g_closure_invoke (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== by 0x916705D: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== by 0x916F714: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== by 0x917012E: g_signal_emit (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== by 0x91585C3: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== Address 0x4029f00 is in a rwx anonymous segment

==18887==

==18887== Invalid free() / delete / delete[] / realloc()

==18887== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==18887== by 0xA95DD09: _XFreeDisplayStructure (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)

==18887== by 0xA94AE7E: XCloseDisplay (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)

==18887== by 0x12331FC8: atspi_get_a11y_bus (in /usr/lib/x86_64-linux-gnu/libatspi.so.0.0.1)

==18887== by 0xD2DEE89: atk_bridge_adaptor_init (in /usr/lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0.0.0)

==18887== by 0x85D3B03: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)

==18887== by 0x8774498: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)

==18887== by 0x915410C: g_closure_invoke (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== by 0x916705D: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== by 0x916F714: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== by 0x917012E: g_signal_emit (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== by 0x91585C3: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.3)

==18887== Address 0x4029f10 is in a rwx anonymous segment
...
...

==20545== More than 1000 different errors detected.  I'm not reporting any more.
==20545== Final error counts will be inaccurate.  Go fix your program!
==20545== Rerun with --error-limit=no to disable this cutoff.  Note
==20545== that errors may occur in your program without prior warning from
==20545== Valgrind, because errors are no longer being displayed.
==20545== 

Debugging with GDB gives:

$ gdb /usr/local/bin/wxformbuilder
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/local/bin/wxformbuilder...done.
(gdb) go
Command requires an argument.
(gdb) run
Starting program: /usr/local/bin/wxformbuilder
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
***MEMORY-ERROR***: wxformbuilder[22214]: GSlice: assertion failed: aligned_memory == (gpointer) addr
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff4aa7e97 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff4aa9801 in __GI_abort () at abort.c:79
#2  0x00007ffff23496b4 in  () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#3  0x00007ffff234a0db in  () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#4  0x00007ffff234ad1e in g_slice_alloc () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#5  0x00007ffff234ad99 in g_slice_alloc0 () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#6  0x00007ffff38ad925 in g_type_create_instance () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#7  0x00007ffff388e748 in  () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#8  0x00007ffff388fee5 in g_object_new_with_properties () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#9  0x00007ffff3890961 in g_object_new () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#10 0x00007ffff3b3dbda in  () at /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
#11 0x00007ffff3b2de3d in  () at /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
#12 0x00007ffff3b02d5d in gdk_display_manager_open_display () at /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
#13 0x00007ffff3ff267a in gtk_init_check () at /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#14 0x00007ffff64324ae in wxApp::Initialize(int&, wchar_t**) () at /usr/local/lib/libwx_gtk3u_core-3.1.so.3
#15 0x00007ffff5a53b9d in wxEntryStart(int&, wchar_t**) () at /usr/local/lib/libwx_baseu-3.1.so.3
#16 0x00007ffff5a545aa in wxInitialize(int&, wchar_t**) () at /usr/local/lib/libwx_baseu-3.1.so.3
#17 0x00007ffff5a545fb in wxEntry(int&, wchar_t**) () at /usr/local/lib/libwx_baseu-3.1.so.3
#18 0x0000555555634d58 in main(int, char**) (argc=1, argv=0x7fffffffded8) at ../src/maingui.cpp:83

Tuesday, January 15, 2019

Fast String Reversal

Prime Number checking of Fibonacci sequence Number

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// (c) 2019, Lutfi Shihab


#include <iostream>
#include <vector>
// todo
template <typename T>
class Matrix
{
public:
    Matrix(int rows, int cols) : m_rows(rows), m_cols(cols) {}
    
private:
    int m_rows;
    int m_cols;
};

 
/* function that returns nth Fibonacci number */
template <typename T>
class Fibonacci
{
public:
    Fibonacci(T n) { m_fibNum = fib(n); }
    operator T() const { return m_fibNum; }
    operator int() const { return m_fibNum; }
    
    friend std::ostream& operator<<(std::ostream& os, Fibonacci<T>&  f)
    {
        return os << f.m_fibNum;
    }
    
    Fibonacci<T> operator+=(int k) { return m_fibNum += k; }
    Fibonacci<T> operator %(int k) { return m_fibNum % k; }
    Fibonacci<T> operator /(int k) { return m_fibNum / k; }
    bool         operator<=(int k) { return m_fibNum < k; }
    bool         operator >(int k) { return m_fibNum > k; }
    bool         operator==(int k) { return m_fibNum == k; }

 private:
    void multiply(T F[2][2], T M[2][2])
    {
        T x =  F[0][0]*M[0][0] + F[0][1]*M[1][0]; 
        T y =  F[0][0]*M[0][1] + F[0][1]*M[1][1]; 
        T z =  F[1][0]*M[0][0] + F[1][1]*M[1][0]; 
        T w =  F[1][0]*M[0][1] + F[1][1]*M[1][1]; 
  
        F[0][0] = x; 
        F[0][1] = y; 
        F[1][0] = z; 
        F[1][1] = w;
    }

    /* Optimized version of power() */
    void power(T F[2][2], T n)
    {

        if( n == 0 || n == 1) 
            return; 
        T M[2][2] = {{1,1},{1,0}}; 
  
        this->power(F, n/2); 
        multiply(F, F); 
  
        if (n%2 != 0) 
        multiply(F, M); 
    }

    T fib(T n) 
    { 
        T F[2][2] = {{1,1},{1,0}}; 
        if (n == 0) 
        {
            return 0;
        }
        power(F, n-1); 
  
        return F[0][0]; 
    } 


    T       m_fibNum;
};

  

// Returns n! (the factorial of n)
int Factorial(int n) 
{
    int result = 1;
    for (int i = 1; i <= n; i++) 
    {
        result *= i;
    }

    return result;
}


// Returns true if n is a prime number
template<typename T>
bool IsPrime(T n) 
{
  // Trivial case 1: small numbers
    if (n <= 1) return false;

    // Trivial case 2: even numbers
    if (n % 2 == 0) return n == 2;

    // Now, we have that n is odd and n >= 3.

    // Try to divide n by every odd number i, starting from 3
    for (T i = 3; ; i += 2) 
    {
        // We only have to try i up to the squre root of n
        if (i > n/i) break;

        // Now, we have i <= n/i < n.
        // If n is divisible by i, n is not prime.
        if (n % i == 0) return false;
    }

    // n has no integer factor in the range (1, n), and thus is prime.
    return true;
}



int main()
{
    for(int i=0; i<300; ++i)
    {
        Fibonacci<unsigned long> f(i);
        if (IsPrime(f))
        {
            std::cout << f << " is a prime number\n";
        }
    }
}

Friday, November 30, 2018

Cheap Signal Analyzer



I bought this very cheap 8-input signal analyzer sometime ago on E-Bay, but since then never had time to use it, mostly due to the driver available was for Windows only.  But a few days ago, I plugged it in on my Linux Mint and googled based on VID I found, I stumbled upon a cool opensource project called "SigOk", a complete project to support various embedded instruments, including my signal analyzer.  It comes with a nice GUI front-end called "PulseView".

Operator Overloading in C++

// Assignment operators:
Type &operator&=(Type &lhs, const Type &rhs); // Assign bitwise and
Type &operator^=(Type &lhs, const Type &rhs); // Assign exclusive or
Type &operator|=(Type &lhs, const Type &rhs); // Assign bitwise or
Type &operator-=(Type &lhs, const Type &rhs); // Assign difference
Type &operator<<=(Type &lhs, const Type &rhs); // Assign left shift
Type &operator*=(Type &lhs, const Type &rhs); // Assign product
Type &operator/=(Type &lhs, const Type &rhs); // Assign quotient
Type &operator%=(Type &lhs, const Type &rhs); // Assign remainder
Type &operator>>=(Type &lhs, const Type &rhs); // Assign right shift
Type &operator+=(Type &lhs, const Type &rhs); // Assign sum

//Other modification operators
Type &operator--(Type &lhs); // Prefix decrement - decrement and return new value
Type operator--(Type &lhs, int unused); // Postfix decrement - decrement and return copy of old value
Type &operator++(Type &lhs); // Prefix increment - increment and return new value
Type operator++(Type &lhs, int unused); // Postfix increment - increment and return copy of old value

//Comparison operators
bool operator==(const Type &lhs, const Type &rhs); // Equal
bool operator>(const Type &lhs, const Type &rhs); // Greater than
bool operator>=(const Type &lhs, const Type &rhs); // Greater than or equal
bool operator<(const Type &lhs, const Type &rhs); // less than
bool operator<=(const Type &lhs, const Type &rhs); // less than or equal
bool operator!(const Type &lhs); // logical complement
bool operator!=(const Type &lhs, const Type &rhs); // no equal
//Other operators
Type operator+(const Type &lhs, const Type &rhs); // Addition
Type operator+(const Type &lhs); // Unary plus
Type operator-(const Type &lhs, const Type &rhs); // Subtraction
Type operator-(const Type &lhs); // Unary minus
ContainedType* operator&(const Type &lhs); // Address of
Type operator&(const Type &lhs, const Type &rhs); // Bitwise and
Type operator~(const Type &lhs, const Type &rhs); // Bitwise complement
Type operator^(const Type &lhs, const Type &rhs); // Bitwise exclusive or
Type operator|(const Type &lhs, const Type &rhs); // Bitwise or
Type operator/(const Type &lhs, const Type &rhs); // Division
Type operator<<(const Type &lhs, const Type &rhs); // Left shift
Type operator*(const Type &lhs, const Type &rhs); // Multiplication
ContainedType &operator*(const Type &lhs); // Dereference
Type operator%(const Type &lhs, const Type &rhs); // Remainder
Type operator>>(const Type &lhs, const Type &rhs); // Right shift

class Type
{
 
// Overloads which must be member functions
  ContainedType &operator[](const IndexType &index); // Array subscript
  Type &operator=(const Type &rhs); // Assignment
  ContainedType &operator->*(); // Member reference
  const ContainedType &operator->*() const; // Member reference
  ContainedType &operator->(); // Member reference
  const ContainedType &operator->() const; // Member reference
 
 // Assignment operators
  Type &operator&=(const Type &rhs); // Assign bitwise and
  Type &operator^=(const Type &rhs); // Assign exclusive or
  Type &operator|=(const Type &rhs); // Assign bitwise or
  Type &operator-=(const Type &rhs); // Assign difference
  Type &operator<<=(const Type &rhs); // Assign left shift
  Type &operator*=(const Type &rhs); // Assign product
  Type &operator/=(const Type &rhs); // Assign quotient
  Type &operator%=(const Type &rhs); // Assign remainder
  Type &operator>>=(const Type &rhs); // Assign right shift
  Type &operator+=(const Type &rhs); // Assign sum
//Other modification operators
  Type &operator--(Type &lhs); // Prefix decrement - decrement and return new value
  Type operator--(Type &lhs, int unused); // Postfix decrement - decrement and return copy of old value
  Type &operator++(); // Prefix increment - increment and return new value
  Type operator++(int unused); // Postfix increment - increment and return copy of old value
//Comparison operators
  bool operator==(const Type &rhs) const; // Equal
  bool operator>(const Type &rhs) const; // Greater than
  bool operator>=(const Type &rhs) const; // Greater than or equal 
  bool operator<(const Type &rhs) const; // Less than
  bool operator<=(const Type &rhs) const; // Less than or equal
  bool operator!=(const Type &rhs) const; // Not equal
//Other operators
  Type operator+(const Type &rhs) const; // Addition
  Type operator+() const; // Unary plus
  Type operator-(const Type &rhs) const; // Subtraction
  Type operator-() const; // Unary minus
  ContainedType* operator&(); // Address of
  const ContainedType* operator&() const; // Address of
  Type operator&(const Type &rhs) const; // Bitwise and
  Type operator~(const Type &rhs) const; // Bitwise complement
  Type operator^(const Type &rhs) const; // Bitwise exclusive or
  Type operator|(const Type &rhs) const; // Bitwise or
  ContainedType &operator*(); // Dereference
  const ContainedType &operator*() const; // Dereference
  Type operator/(const Type &rhs) const; // Division
  Type operator<<(const Type &rhs) const; // Left shift
  bool operator!() const; // Logical complement
  Type operator*(const Type &rhs) const; // Multiplication
  Type operator%(const Type &rhs) const; // Remainder
  Type operator>>(const Type &rhs) const; // Right shift
};


Example


Type& Type::operator = (Type const & rhs)
{
    if (&rhs != this)
    {
        // perform assignment to the class T's attributes
    }
    // return by reference
    return *this;
}


Type Type::operator &= (Type const & rhs)
{
    return *this = (*this) & rhs;
}


Type Type::operator & (Type const & rhs)
{
    Type newObjVal;

    // do customized bitwise AND for the type against rhs
    ….

    // return an object by value
    return newObjVal;
}

Type& Type::operator++()  // prefix
{
    ++m_data;
    return *this;
}



class MyClass
{
public:
    // conversion operator, so expression like: Type b = myClass;
    operator Type() { return *m_ptr; }
...
private:
    int m_data;
    Type m_ptr;
};

MyClassMyClass::operator++(int unused)  // postfix
{
    MyClassresult = *this;
    ++m_data;
    // return value before increment
    return result;
}


T* MyClass::operator->() const {return m_ptr; }

// Conversion operator