顯示具有 c 標籤的文章。 顯示所有文章
顯示具有 c 標籤的文章。 顯示所有文章

2012/08/01

Ignore SIGPIPE in socket programming

通常在寫 socket programming 時,系統對一個 invalid fd (file descriptor) 做寫入時會讓系統丟出 SIGPIPE 的 signal,為了避免程式被中斷,通常都會 ignore 它。

#include <signal.h>
struct sigaction sa;

sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;

sigemptyset(&sa.sa_mask);
sigaction(SIGPIPE, &sa, 0);

2012/06/26

C compile 常見的錯誤

C 語言是我最熟悉的語言,通常我用它的時候都是講求效能,但顧效能的同時也需要花費更多心力(效率降低)。抓 memory leak、segmentation fault 這些都很要命,當然用對工具可以讓你 debug 速度加快很多,gdb、valgrind、oprofile 也都是必學的。由於沒有 OO 概念,常常需要用 structure 跟 point 去模擬物件、封裝,專案寫大的時候就會很難維護。

下面把我常遇到的 compile error 列出來:

No such file or directory
$ gcc -o test test.c
test.c:2:23: error: json/json.h: No such file or directory
test.c: In function 'main':
test.c:8: warning: assignment makes pointer from integer without a cast
test.c:12: warning: assignment makes pointer from integer without a cast
表示 include 的 header file 找不到,預設會去找 /usr/include、/usr/local/include,若 library 安裝在其他目錄,可以在 compile 時加上 -I/opt/json-c-0.9/include。


Undefined reference
$ gcc -o test test.c -I/opt/json-c-0.9/include
/tmp/ccMCrNFo.o: In function `main':
test.c:(.text+0x9): undefined reference to `json_object_new_object'
test.c:(.text+0x17): undefined reference to `json_object_new_string
...
test.c:(.text+0xc1): undefined reference to `json_object_put'
collect2: ld returned 1 exit status
表示 link library 失敗,compile 時要加上 -ljson


Linking fail
$ gcc -o test test.c -I/opt/json-c-0.9/include -ljson
/usr/bin/ld: cannot find -ljson
collect2: ld returned 1 exit status
表示找不到 libjson.so 的 library 檔案,預設的搜尋路徑 /lib、/lib64、/usr/lib、/usr/local/lib, 若 library 安裝在其他地方,在 compile 時要加上 -L/opt/json-c-0.9/lib 來增加搜尋的路徑。


Implicit declaration of function
$ gcc -Wall -o test test.c test2.o -I/opt/json-c-0.9/include -L/opt/json-c-0.9/lib -ljson
test.c: In function 'main':
test.c:23: warning: implicit declaration of function 'sub_func'
出現此 warning,表示你用的 function 在 .c 檔中有定義,但是没有在對應的 header 檔中宣告。
上例中我在 test.c 去 call sub_func() 這個 function,這個 function 是在 test2.c 中 implement,但卻沒有在 test2.h 宣告。


Error while loading shared libraries
$./test
./test: error while loading shared libraries: libjson.so.0: cannot open shared object file: No such file or directory
表示 runtime 時 load 不到指定的 library,環境變數 $LD_LIBRARY_PATH 要加入 share library 路徑,LD_LIBRARY_PATH=/opt/json-c-0.9/lib

2012/06/25

JSON parser in C language - json-c

C 語言存取 JSON 格式的資料實在不是很方便,不像 python、javascript 原生的物件表示法就跟 JSON 一樣。C 的 implementation 在官網列了好幾套,我自己是選用 json-c

API 使用方式可以參考這裡

這邊就列出基本的操作,以這樣為例:
{
  "name": "Brian",
  "sex": 0,
  "data": {
    "education": "master",
    "profession": "engineer"
  }
}

組成 JSON object,並輸出成 string
struct json_object *root, *data;

root = json_object_new_object();
json_object_object_add(root, "name", json_object_new_string("Brian"));
json_object_object_add(root, "sex", json_object_new_int(0));

data = json_object_new_object();
json_object_object_add(data, "education", json_object_new_string("master"));
json_object_object_add(data, "profession", json_object_new_string("engineer"));
json_object_object_add(root, "data", data);

// Output to string
printf("%s", json_object_to_json_string(root));

// Decrease counter and free object
json_object_put(data);
json_object_put(root);

解開 JSON object
struct json_object *root, *name, *sex, *data, *edu, *prof;

root = json_tokener_parse(json_string);
// Use is_error() to check the result, don't use "j_root == NULL".
if (is_error(j_root)) {
  printf("parse failed.");
  exit(-1);
}

name = json_object_object_get(root, "name");
sex = json_object_object_get(root, "sex");
data = json_object_object_get(root, "data");
// If parse fail, object is NULL
if (data != NULL) {
  edu = json_object_object_get(data, "education");
  prof= json_object_object_get(data, "profession");
}

if (!name || !sex|| !edu || !prof) {
  printf("parse failed.");
  json_object_put(root);
  exit(-1);
}

// Fetch value
printf("name=%s", json_object_get_string(name));
printf("sex=%d", json_object_get_int(sex));
printf("education=%s", json_object_get_string(edu));
printf("profession=%s", json_object_get_string(prof));

// Free
json_object_put(root);

參考資料
json-c-0.9库的json_object_object_get()引发崩溃问题

2012/03/27

編譯 binary 的時候自動加入 release version 與 date

Makefile
SVN_VERSION = "\"`svn info | grep Revision | sed 's/Revision: //g'`\""
BUILD_TIME = "\"`date '+%Y/%m/%d %H:%M:%S'`\""

CFLAGS += -DSVN_VERSION=$(SVN_VERSION) -DBUILD_TIME=$(BUILD_TIME)

.c 檔
void show_version (void)
{
    printf("SVN Version: %s, Bulid time: %s\n", SVN_VERSION, BUILD_TIME);
}
Preprocessing 的時候 macro 會自動被帶換掉啦!