いやーっ、ハマったね、iconv。 たとえば下のようなことをやると、printf() での変数 outbuf は、変換後の文字列の先頭へのポインタとならない。
char *inbuf, *outbuf;
size_t inbufleft, outbufleft;
.... 省略 ....
inbufleft = strlen(inbuf);
outbufleft = BUFSIZE;
outbuf = calloc(BUFSIZE, sizeof(char));
iconv(cd, &inbuf, &inbufleft, &outbuf, &outbufleft);
printf("%s\n", outbuf);
上の場合、変換後の文字列の最後の部分 (文字 '\0')へのポインタとなっている。 outbuf に保持されるポインタの値を iconv() が書き換えている。 なので、以下のように書くと、期待していたとおりに動いてくれる。
char *in, *out, *inbuf, *outbuf;
size_t inbufleft, outbufleft;
.... 省略 ....
inbuf = in;
inbuflen = strlen(inbuf);
outbuflen = BUFSIZE;
out = outbuf = calloc(BUFSIZE, sizeof(char));
iconv(cd, &inbuf, &inbufleft, &outbuf, &outbufleft);
printf("%s\n", out);
free(out);
char* 型の変数 in, out に、それぞれの始点ポインタを保持させておくことが重要。 iconv() 実行後は out != outbuf な状態になる。 これに気づくのに数時間かけてしまった.... のである。