>Тема достаточно избитая - cp1251 vs koi8-r. С помощью man iconv(3) и >этого форума наваял рабочий вариант: > >string convert(string from, string to, const char *enc1, const char *enc2) { > > iconv_t cd = (iconv_t)(-1); > cd = iconv_open(enc1, enc2); > if( cd == (iconv_t)(-1) ) > cerr << "-ERR: iconv_open(" ><< enc1 << ", " << enc2 << ");\n"; > > size_t nrc, oldlen, buflen; > char* in = new char(from.size() + 1); > char* out = new char(from.size() * 4 + >1); > char* out_pointer = out; > strcpy(in, from.data()); > oldlen = from.size(); > buflen = oldlen * 4; > memset( out, 0, buflen); > cout << "IN: " << in << endl; > > nrc = iconv(cd, &in, &oldlen, &out_pointer, &buflen); > cout << "OUT: " << out << endl; > > cout << "Non-reversibly converted: " << nrc << >"\n"; > nrc = iconv(cd, NULL, NULL, NULL, NULL);//This is >really needed in multi-thread program only > cout << "We are just before iconv_close\n"; > if (iconv_close(cd) != 0) > cerr << "-ERR: iconv_close();\n"; > > to.copy(out, strlen(out)); > delete in, out; > return to; >} > >Везде, где 'cout <<' - подразумевается #ifdef DEBUG .. #endif :) > >Conversion descriptor создаётся, строки конвертируются корректно, всё работает. Но при вызове iconv_close(cd) >программа хватает SIGSEGV в функции mallopt() glibc. >Версия glibc: glibc-2.3.4.20041102 > >Если не вызывать iconv_close(), то вылетает iconv_open() при следующем её вызове. >Проблему можно конечно решить, создав 6 дескрипторов koi-8<=>cp1251<=>utf-8, но мало ли - понадобится допустим ещё и koi8-u. > >До кучи, если немного поиграться и сдвинуть строки > iconv_t cd; > cd = iconv_open(enc1, enc2); > if( cd == (iconv_t)(-1) ) > cerr << "-ERR: iconv_open(" ><< enc1 << ", " << enc2 << ");\n"; >вплотную к вызову iconv(), то вылетает первый же вызов iconv_open() > >Я, конечно, в курсе, что mallopt() is obsoleted в пользу malloc(), но >мне свободу выбора вроде как никто не предоставляет :) > >Кто-нибудь может подсказать, как эту беду побороть? Знаешь, вот такая конструкция уже работает 100 лет без сбоев: void WWWDataToken::iconv_recode(string from, string to, string & text) { if (from==to) return; iconv_t cnv = iconv_open(to.c_str(), from.c_str()); if (cnv==(iconv_t)-1) return; char *outbuf; if ((outbuf=(char *)malloc(text.length()*2+1))==NULL) return; char *ip=(char *)text.c_str(), *op=outbuf; size_t icount=text.length(), ocount=text.length()*2; if (iconv(cnv, &ip, &icount, &op, &ocount)!=(size_t)-1) { outbuf[text.length()*2-ocount]='\0'; text=outbuf; } free(outbuf); iconv_close(cnv); } Что смущает у тебя, так это вот это вот > nrc = iconv(cd, NULL, NULL, NULL, NULL); Нигде в манах по iconv ничего не нашел про то, что указатели на длины буферов можно ставить в NULL.
|