Search code examples
c++clinuxiconvlibiconv

How to use libiconv correctly in C so that it would not report "Arg list too long"?


Code

/*char* to wchar_t* */
wchar_t*strtowstr(char*str){
    iconv_t cd=iconv_open("wchar_t","UTF-8");
    if(cd==(iconv_t)-1){
        return NULL;
    }
    size_t len1=strlen(str),len2=1024;
    wchar_t*wstr=(wchar_t*)malloc((len1+1)*sizeof(wchar_t));
    char*ptr1=str;
    wchar_t*ptr2=wstr;
    if((int)iconv(cd,&ptr1,&len1,(char**)&ptr2,&len2)<0){
        free(wstr);
        iconv_close(cd);
        return NULL;
    }
    *ptr2=L'\0';
    iconv_close(cd);
    return wstr;
}

I use strerror(errno) to get the error message,it says "Arg list too long".
How can I solve it? Thanks to the comments,I change the code above.
I just use the function to read a text file.I think it reports the error because the file is too large.So I want to know how to use iconv for long string.


Solution

  • According to the man page, you get E2BIG when there's insufficient room at *outbuf.

    I think the fifth argument should be a number of bytes.

    wchar_t *utf8_to_wstr(const char *src) {
        iconv_t cd = iconv_open("wchar_t", "UTF-8");
        if (cd == (iconv_t)-1)
            goto Error1;
    
        size_t src_len = strlen(src);                 // In bytes, excludes NUL
        size_t dst_len = sizeof(wchar_t) * src_len;   // In bytes, excludes NUL
        size_t dst_size = dst_len + sizeof(wchar_t);  // In bytes, including NUL
        char *buf = malloc(dst_size);
        if (!buf)
            goto Error2;
    
        char *dst = buf;
        if (iconv(cd, (char**)&src, &src_len, &dst, &dst_len) == (size_t)-1)
            goto Error3;
    
        *(wchar_t*)dst = L'\0';
        iconv_close(cd);
        return (wchar_t*)buf;
    
    Error3:
        free(buf);
    Error2:
        iconv_close(cd);
    Error1:
        return NULL;
    }