2013年7月1日 星期一

strcmp() 傳 NULL 進去的神秘現象...

作業環境:
Linux li475-173 3.5.2-linode45 #1 SMP Wed Aug 15 14:10:55 EDT 2012 i686 GNU/Linux
gcc version 4.4.5 (Debian 4.4.5-8)

-

test code: (已經簡化到最少)

#include <stdio.h>
#include <string.h>

int main(void)
{
    char *na = NULL;
    char *nb = NULL;
    int ret = 1234;

    strcmp(NULL, NULL);  // case 1
    strcmp(na, nb);  // case 2
    ret = strcmp(NULL, NULL);  // case 3
    ret = strcmp(na, NULL);  // case 4
    ret = strcmp(NULL, nb);  // case 5
    ret = strcmp(na, nb);  // case 6

    printf("%d\n", ret);

    return 0;
}

case 1-6 只會使用其中一行進行編譯(gcc test.c), 不加其他編譯參數.

若加上 -Wall 可以看到類似這樣的警告訊息:
warning: null argument where non-null required

-

case 1 2 3 可以執行無誤, case 4 5 6 都會噴 Segmentation fault

-rwxr-xr-x  1 slzzp admin      4520 Jul  1 20:35 a.out.1
-rwxr-xr-x  1 slzzp admin      4520 Jul  1 20:36 a.out.2
-rwxr-xr-x  1 slzzp admin      4520 Jul  1 20:36 a.out.3
-rwxr-xr-x  1 slzzp admin      4622 Jul  1 20:36 a.out.4
-rwxr-xr-x  1 slzzp admin      4622 Jul  1 20:36 a.out.5
-rwxr-xr-x  1 slzzp admin      4622 Jul  1 20:36 a.out.6

b3b2d33b3f5dca1b9df14eed6056d216  a.out.1
b3b2d33b3f5dca1b9df14eed6056d216  a.out.2
015e405413b165b7539f3dfd6f0601f2  a.out.3
2e64c7055fae7e606412ef2adede6d87  a.out.4
8b620ac644f8a18e5cbb953d19b8ede5  a.out.5
d8987fb39dbb7046b772cb86a11f149e  a.out.6

故意把 case 1 跟 case 2 多複製幾行, 編譯後的 a.out 檔案大小跟 md5 
都相同, case 3 的執行結果 ret 是 0, 應該都被自動 -O 過了.

所以 case 1 2 3 根本沒進去 strcmp 執行過... oroz

補充: ret 是 0 表示 strcmp() 的結果是 TRUE, 理論上來說 NULL 跟 NULL
相比的確是一樣的沒錯.


那 case 4 5 6 的狀況呢...

查了幾下之後, 得到這個結論:
Passing a null pointer to strcmp() results in undefined behaviour.
Don't do it.

--
嗚嗚, libc/strcmp 沒有做防呆檢查...
只好再想想 test unit / test process 要怎麼改了... T_T