boost library naming

參考:
http://www.boost.org/doc/libs/1_66_0/more/getting_started/windows.html#library-naming
https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx

另外 boost/config/autolink.hpp裡有提到lib naming的規則

BOOST_LIB_PREFIX
+ BOOST_LIB_NAME
+ "_"
+ BOOST_LIB_TOOLSET
+ BOOST_LIB_THREAD_OPT
+ BOOST_LIB_RT_OPT
"-"
+ BOOST_LIB_VERSION

On Windows, only ordinary static libraries use the lib prefix; import libraries and DLLs do not.
windows上 static library才有lib prefix

boost_regex-vc140-mt-gd-1_65_1.lib

boost_regex: library name
vc140: toolset tag
mt: multithreading support
gd: g, debug runtime. d, debug. s, static runtime
1_65_1: version tag, 1.65.1

Posted in Library | Leave a comment

nodejs request iconv

在使用nodejs request抓取網頁時,如果需要進行轉碼,則須注意request的callback中body是string or buffer
對於Big5來說 如果轉成javascript string, 此時body在iconv(由big5=>utf8)會失敗。 javascript string假設input是utf8
需要強制body保留原始bytes

request({
url: ...,
method: 'GET',
encoding: null
}, function (err, resp, body){ //body is buffer now
});

在說明文件有提到

encoding - encoding to be used on setEncoding of response data. If null, the body is returned as a Buffer.

此時再利用如iconv的工具進行編碼轉換

Posted in nodejs | Leave a comment

ffmpeg build on windows

根據 https://trac.ffmpeg.org/wiki/CompilationGuide/MSVC 的說明
這邊使用VS2015, 配合msys


如需要啟用yasm選項 => http://yasm.tortall.net/Download.html download yasm.exe => C:\Windows
yasm選項 deprecated

WARNING: The --enable-yasm option is only provided for compatibility and will be
removed in the future. Use --enable-x86asm / --disable-x86asm instead.

msys2 with vs support
msys2 install => https://www.msys2.org/
預設有缺一些套件

pacman -S base-devel --needed
# 選18 (diffutils), 36(make)

C:\msys64\usr\bin\link.exe => C:\msys64\usr\bin\link2.exe (與vc的link.exe衝突)

first open VS2015 command line 注意x64
如果是一般的command line prompt 要執行(vcvarsall.bat amd64)

msys2_shell.cmd -mingw64 -use-full-path

cl.exe確認是否是x64

configure參數:

./configure --disable-x86asm --arch=x86_64  --enable-avresample --disable-ffserver --disable-avdevice --disable-ffplay --disable-ffprobe --disable-ffmpeg --enable-shared --disable-static --disable-bzlib --disable-libopenjpeg --disable-iconv --disable-zlib --prefix=/c/ffmpeg --toolchain=msvc --disable-doc

接下來 make => make install
會輸出在 c:\ffmpeg

Posted in Library | Leave a comment

sqlite3 compilation

sqlite3 compilation on VS2017
出現

1>sqlite3.c(39053): error C4996: 'GetVersionExA': 宣告為已被取代
1>C:\Program Files (x86)\Windows Kits\8.1\Include\um\sysinfoapi.h(433): note: 請參閱 'GetVersionExA' 的宣告
1>sqlite3.c(39063): error C4996: 'GetVersionExW': 宣告為已被取代
1>C:\Program Files (x86)\Windows Kits\8.1\Include\um\sysinfoapi.h(442): note: 請參閱 'GetVersionExW' 的宣告

在 sqite3.c加上 #pragma warning(disable: 4996) 即可

Posted in Library | Leave a comment

mysql install

MySQL install on CentOS 7

從官網下載yum repo
https://dev.mysql.com/downloads/repo/yum/
mysql57-community-release-el7-11.noarch.rpm

安裝

yum -y install mysql-community-server.x86_64

重設root password
如果忘記root密碼 需要重設時 先打開skip-grant-tables選項
可在/etc/my.cnf [mysqld]下加上
skip-grant-tables

/etc/my.cnf
[mysqld]
skip-grant-tables
#...

然後重啟server

mysql -u root
即可登入進去,但注意 重設password會跳出error說還是在skip-grant-tables mode
此時先刷新privileges

flush privileges;

再來將password重設

shell> mysql -u root
mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('new_password');
mysql> SET PASSWORD FOR 'root'@'127.0.0.1' = PASSWORD('new_password');
mysql> SET PASSWORD FOR 'root'@'::1' = PASSWORD('new_password');
mysql> SET PASSWORD FOR 'root'@'%' = PASSWORD('new_password');
Posted in System Administration | Leave a comment

C++ exit abort與destructor

#include 
#include 

class X
{
  int i;
public:
  X(int i): i(i)
  {
  }
  ~X()
  {
    std::cout << "~X," << i <<  std::endl;
  }
};
static X a(0);
int main()
{
  X a(1);
  //exit(0);
  //abort();
  return 0;
}

從main return時 如預期 先呼叫function scope內的X1的destructor,才再是static X0的destructor。
那如果是exit呢? 只有X0 destructor被呼叫。

為什麼呼叫了exit不是強制直接結束程式而還會呼叫static variable destructor?
參考C++03的 18.3 Start and termination

The function exit() has additional behavior in this International Standard:
First, objects with static storage duration are destroyed and functions registered by calling atexit are
called. Non-local objects with static storage duration are destroyed in the reverse order of the completion
of their constructor. (Automatic objects are not destroyed as a result of calling exit().)
...
The function exit() never returns to its caller.

如果要直接強制離開可呼叫abort

The function abort() has additional behavior in this International Standard:
— The program is terminated without executing destructors for objects of automatic or static storage duration and without calling the functions passed to atexit()

但須注意 abort()會產生core dump
在linux下則可以呼叫_exit(0); 要

#include  

參考: https://stackoverflow.com/questions/7054685/are-destructors-run-when-calling-exit

Posted in C++ Language | Leave a comment

css layout

主要參考自: http://learnlayout.com

disaply是在css layout中最基本的property,每一個element都有預設的display property

block: 從新的一行開始盡量佔據(<div>, <p>, <form>)
inline: 不會換行,忽略height, width, margin…etc屬性 (<span>, <a>, <img>)
inline-block: 兼具inline的特點(不換行),但又可以有寬高
none: 不顯示,不佔據空間 (<script> 。比較: visibility: hidden)

參考:
https://developer.mozilla.org/en-US/docs/Web/CSS/display

置中:
margin: 0 auto

position屬性:
預設值:static(等於沒有設定position)
relative必須配合其他屬性才有作用
fixed是保持在網頁的固定位置(relative to viewport),不會被scrollbar影響,適合做浮動的nav bar或是footer
absolute是相對於nearest positioned ancestor(positioned代表不是static)

float屬性: left / right /both 定義了float,會float在後面的div上,除非使用了clear屬性

Posted in Front-end | Leave a comment

exception assert使用時機

exception和assert是完全不同的東西,
assert是用來確認條件與狀態的一致性的方法(用在確定該條件為真,如果不成立,則代表程式有bug),而exception是將錯誤傳遞出去(發生在隱藏錯誤與傳遞錯誤的內外邊界)。

舉例來說 在一些語言裡存取null pointer的方法時會因發exception,假如可以確定不可能是null pointer,則應使用assert來檢查是否有不預期的狀態出現,因為當exception發生時,常常會被外層try catch接住而將問題(bug)屏蔽。導致當系統出現不預期行為時,已經和發生點找不到直接的關聯

另外在switch case中enum變數的值通常會是特定的值,如果在switch block中有default,當問題發生時很可能enum變數的值是invalid直接落入default action而未發現問題,這時候用assert檢查enum值的區間就有意義,這種情況常發生在物件已經是invalid(或指到錯誤的位置)

這些bug常見於multithread的程式開發中,特別是debug相當困難,結果常是莫名的segmentation fault crash,而利用assert來檢查物件的狀態變數是否符合預期,物件的member variable是否落在valid的區間,早期發現問題。

exception常是用在邊界上的錯誤傳遞(邊界的定義不是絕對的,要看context而定,可能細至api被呼叫者與呼叫者的邊界)
assertion可以想成在系統邊界內的所有程式碼,都安全地假設狀態和值都是符合預期
至於assertion要assert什麼?
可以參考programming by contract(C.A.R. Hoare.)這樣的概念
Pre-conditions, Post-conditions, Invariants

對於使用者輸入的邊界檢查很顯然是利用exception而非assert,因為超出邊界並不是bug,
除非是經過一系列檢查後進入系統邊界內,這時候使用assert檢查就合理了

狀態跑掉常見的原因是multithread程式中lock出現問題,從而導致race condition,
另外如果物件被提早釋放掉,object內的function存取部分member variables出現不預期的值,
通常這類情況不會馬上出問題,但很容易在後面出現heap corruption,此時卻不知道是從哪裡造成的。
特別是如果大量使用asynchronous API,更難追蹤來源,並且asynchronous API的callback有可能是不同thread呼叫。
透過使用debugger可以追蹤當下發生中斷的stack frames,但需配合assert,縮小問題可能的發生點。

參考連結:
https://www.edn.com/electronics-blogs/embedded-basics/4440193/8-tips-for-squashing-bugs-using-ASSERT-in-C
https://www.cs.umd.edu/class/fall2002/cmsc214/Projects/P1/proj1.contract.html

Posted in Tips | Leave a comment

shared_ptr + lambda

在C++11裡新支援了lambda, 這也使得編寫C++程式可以多了一些FP的風格。
lambda特別是在處理callback時特別簡潔,因為通常callback function是為了特定api打造的,單獨定義會讓程式碼比較分散,在閱讀上也常會被打斷。

在沒有capture情況下,lambda可以直接當成ordinary function pointer
lambda如果有capture variable, 則可以想像成compiler透過functor的技巧打包,此時不能用在使用function pointer的callback

#include 
typedef void (*callback)(int);
void test(callback cb)
{
  cb(100);
}
int main()
{
  //capture-less lambda, can be treated like function pointer
  test([](int n){
    std::cout << "in lambda, " << n << std::endl;
  });
  return 0;
}

沒有capture variable的lambda function,使用上不需注意太多。但是如果有capture variable,那要特別注意變數生命週期的問題。
第一件事是要先確定該callback是synchronous or asynchronous,synchronous的情況一般也不太會有問題,但asynchronous callback很容易遇到當callback回來時,物件不知道是否仍存在

一個典型的例子是 tcp connection, 在收到資料後回調callback,

class Connection
{
 ...
  void read(std::function cb);
};

conn->read([conn](int len, char* buffer){
   //check len, if <0, error case
   //process something
   //start another read
});

這邊要注意conn存在時間要足夠長,為了避免手動管理物件的存在時間,可以考慮使用shared_ptr
"假如" conn是shared_ptr,以上的code可以直接確保conn一定會在callback時還活著
lamba object因為capture conn, 在執行到read該處時,conn會被複製進lambda object
從而使reference count + 1

Posted in C++ Language | Leave a comment

npm tips

# 查版本
npm --version

# 查看相關環境版本
npm version

{ npm: '5.5.1',
  ares: '1.10.1-DEV',
  cldr: '31.0.1',
  http_parser: '2.7.0',
  icu: '59.1',
  modules: '57',
  nghttp2: '1.25.0',
  node: '8.9.1',
  openssl: '1.0.2m',
  tz: '2017b',
  unicode: '9.0',
  uv: '1.15.0',
  v8: '6.1.534.47',
  zlib: '1.2.11' }

#起始一個project產生package.json
npm init 
#但是會問一些問題設定, 太麻煩了, 可直接使用 -y 略過問題
npm init --yes
npm init -y
#要改變 -y 產生的預設值 可用 npm config
#例如
$ npm set init.author.name "xxx"
$ npm set init.license "MIT"
# 會存在 .npmrc

# 安裝package, 預設情況下儲存版本會使用 ^version
npm install request --save
# ~version "Approximately equivalent to version" 
# ^version "Compatible with version"  (鎖住major version)
# 1.2.x 1.2.0, 1.2.1, etc., but not 1.3.0
# 關於版本的描述可參考
# https://docs.npmjs.com/misc/semver 有詳細的介紹

# 鎖住package和dependency版本
$ npm shrinkwrap
產生 npm-shrinkwrap.json

# 檢查各package目前版本與最新版本
$ npm outdated
# 再用 npm update 更新
# dev dependencies
$ npm install xxx --save-dev
# 安裝(dev)
npm install --production
# 也可以用
$ NODE_ENV=production npm install

# 設定檔
~/.npmrc

# 更新npm 注意nodejs版本也會影響到npm的執行
$ npm install npm@latest -g

# npm -g 會安裝到 /usr/local/lib/node_modules/ 以及/usr/local/bin symlink
# 根據 npm config get prefix
$ npm config get prefix
/usr/local
# npm host
# see https://github.com/npm/npm-registry-couchapp

# npm package name conflict event
# http://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm

# npm v3 remove dup
npm dedupe

# npm 會認 .npmignore, 如果沒有則看 .gitignore

# 打包成proj-x.x.x.tar.gz 會解開到 package
$ npm pack
Posted in nodejs | Leave a comment