2024年12月15日 星期日

C++17 好用的 tuple 的 auto 解構

Gemini 說這功能是在 C++17 之後才有的。
#include <iostream>
#include <vector>
#include <tuple>

using namespace std;

int main()
{
	vector<tuple<int,int,double>> box;
	for (int i{1}; i < 10; ++i)
		box.push_back(make_tuple(i, i*i, (double)i/(i*i)));
	for (auto [idx, square, value]: box)
		cout << idx << " " << square << " " << value << endl;
	while (!box.empty()) {
		auto [idx, square, value] = box.back();
		box.pop_back();
		cout << idx << " " << square << " " << value << endl;
	}
	return 0;
}

2024年11月29日 星期五

C++ 的 std::string::size() 使用上要小心的地方

std::string::size() 的回傳會是 size_t 這樣的無號正整數或零的型別。

我在刷 LeetCode 的題目時寫出了這樣的程式碼。

class Solution {
public:
    int strStr(string haystack, string needle) {
        for (int i = 0; i <= haystack.size() - needle.size(); i++) {
        	// ...
        }
        return -1;
    }
};

當 needle 比 haystack 還要長時,其運算結果原以為會是負數,但是因為無號正整數或零的型別,就會被轉成正整數,導致 for 迴圈中會透過 i 去使用到 haystack 或是 needle 以外的記憶體位址,導致程式崩潰。

${shlibs:Depends} 使用上的一些陷阱

其實 0~git202411270842.3c1cdd3 這樣的 Debian Version 會等於 0~git202411270842.3c1cdd3-0

$ dpkg --compare-versions 0~git202411270842.3c1cdd3-0 eq 0~git202411270842.3c1cdd3; echo $?
0

於是 0~git202411270842.3c1cdd3-0~ 這樣的 Debian Version 就會小於 0~git202411270842.3c1cdd3

$ dpkg --compare-versions 0~git202411270842.3c1cdd3-0~ lt 0~git202411270842.3c1cdd3; echo $?
0

例如套件 A 使用了 0~git202411270842.3c1cdd3-0~ 這樣的版號。

陷阱來自於在套件 B 的 debian/control 裡面相依性使用 ${shlibs:Depends} 時,只會找到套件 A 的 upstream version 而已,然後會自動代入 (>= 0~git202411270842.3c1cdd3) 這樣的版號相依。

於是在套件 B 的 Debian packaging 打包後,就會遇到明明套件 B 的 Debian source packages 可以成功編譯成 Debian binary packages,但是卻無法安裝使用的情況。

$ sudo apt install libcamhal-ipu6ep
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 libcamhal-ipu6ep : Depends: libbroxton-ia-pal-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libgcss-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-aiq-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-aiqb-parser-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-bcomp-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-cca-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-cmc-parser-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-coordinate-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-dvs-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-emd-decoder-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-exc-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-isp-bxt-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-lard-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-log-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-ltm-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-mkn-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
                    Depends: libia-nvm-ipu6ep0 (>= 0~git202411270842.3c1cdd3) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

至於解決方法就是避免使用比 0~git202411270842.3c1cdd3-0 還要小的版號,像是可以改用 0~git202411270842.3c1cdd3-1~ 這樣的版號就不會產生問題了。

$ dpkg --compare-versions 0~git202411270842.3c1cdd3-1~ gt 0~git202411270842.3c1cdd3; echo $?
0

以上是測試打包 ppa:oem-solutions-group/intel-ipu6 時的一些心得感想。

2020年4月23日 星期四

以後的筆記要搬到 https://hackmd.io/@fourdollars 上面囉

本來打算將 Autopkgtest 初體驗 這篇筆記搬回來 Blogger,突然發現這樣好像有點在浪費時間。

因為 HackMD - Markdown 協作知識庫 實在是太好用了,功能都很完整(至少我需要的都有),所以以後不打算再維護這邊了。

https://hackmd.io/@fourdollars

2019年11月22日 星期五

在 Ubuntu 18.04 透過 postfix 來使用 Gmail 寄信

以下內容是參考 https://kifarunix.com/configure-postfix-to-use-gmail-smtp-on-ubuntu-18-04/

首先安裝一下 postfix 與 mailutils

$ sudo apt install postfix mailutils

安裝過程設定使用 Internet site: Mail is sent and received directly using SMTP.

安裝後修改 /etc/postfix/main.cf

relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

修改 /etc/postfix/sasl_passwd 加入密碼

[smtp.gmail.com]:587 userid@gmail.com:password

應用程式密碼可以在 https://myaccount.google.com/apppasswords 產生

使用 postmap 產生 db

$ sudo postmap /etc/postfix/sasl_passwd
$ ls /etc/postfix/sasl_passwd*
/etc/postfix/sasl_passwd  /etc/postfix/sasl_passwd.db

變更 /etc/postfix/sasl_passwd* 權限

$ sudo chown root:root /etc/postfix/sasl_passwd*
$ sudo chmod 600 /etc/postfix/sasl_passwd*

設定完成後重啟 postfix

$ service postfix reload

最後寫一封信寄給自己看看有沒有成功收到

$ echo "This is a test mail." | mail -s "test mail" userid@gmail.com

2018年7月27日 星期五

自製 Ubuntu 16.04.X/17.10/18.04.X/18.10 測試硬體安裝使用的 USB 隨身碟

與「自製 Ubuntu 13.04/12.10/12.04.2 與 Debian 7.0 測試硬體安裝使用的 USB 隨身碟」跟「自製 Ubuntu 16.04/16.04.1/16.04.2/16.10/17.04 測試硬體安裝使用的 USB 隨身碟」同樣的步驟只是改用 grub.cfg 這個設定檔。

隨身碟換成某年在 COSCUP 購買的 USB stick 紀念品,所以容量有 16GB 可以用,只是已經不想再不斷地修改 grub.cfg 所以改成自動偵測 vmlinuz 跟 initrd 的檔案名稱,然後會去掃 iso 目錄底下的所有 iso 檔,之後只要爽爽地將新的 iso 檔複製到 iso 目錄底下就會自動找到了,不用在因為新增或刪除 iso 檔而去修改 grub.cfg。

主要修改的部份如下:

for isofile in /iso/*.iso
do
    menuentry "試用 $isofile 免安裝 ($bios)" $isofile {
        loopback loop $2

        if [ -f (loop)/casper/vmlinuz ]; then
            set vmlinuz="(loop)/casper/vmlinuz"
        elif [ -f (loop)/casper/vmlinuz.efi ]; then
            set vmlinuz="(loop)/casper/vmlinuz.efi"
        fi

        if [ -f (loop)/casper/initrd ]; then
            set initrd="(loop)/casper/initrd"
        elif [ -f (loop)/casper/initrd.lz ]; then
            set initrd="(loop)/casper/initrd.lz"
        elif [ -f (loop)/casper/initrd.gz ]; then
            set initrd="(loop)/casper/initrd.gz"
        fi

        linux   $vmlinuz iso-scan/filename=$2 $options $desktop --- $extra
        initrd  $initrd
    }
done

2017年11月26日 星期日

線上編輯與分享 Debian 與 Ubuntu 的自動安裝設定

多年前在弄 https://fourdollars.github.io/d-i/ 時,就已經想到這個主意了,趁這個週末有點時間就用 Python Flask 硬幹出來。

主要是利用下面的機制做出來的:

運作的原理是根據使用者的 IPv4 位址來儲存設定檔,所以另一台透過同樣的 IPv4 位址就可以拿到同一份設定檔,分享的時候也是透過分享 IPv4 位址來達成,但是只有該 IPv4 位址的使用者才能夠編輯給該 IPv4 位址使用的設定。

專案網址:https://fourdollars.github.io/diaas/

我另外弄了一個專門給 Ubuntu 台灣中文社群的通用設定在 https://sylee.org/d-i/?share=08080808,點進去後按下 Save 就可以使用了。