Как отобразить строки Unicode при отладке в Linux - PullRequest
5 голосов
/ 12 ноября 2009

Я работаю уже несколько лет как C ++ Developer, используя MS Visual Studio в качестве рабочей платформы. Так как я в частном порядке предпочитаю использовать Linux, я недавно взял шанс перенести мою рабочую среду в Linux. Так как я оптимизирую свою среду Windows уже несколько лет, конечно, оказывается, что некоторые вещи отсутствуют или работают не так, как ожидалось. Таким образом, у меня есть несколько вопросов, на которые я пока не смог дать полезных ответов.

Давайте начнем следующую проблему, другие вопросы, вероятно, последуют позже. Проблема в том, что я уже сталкивался несколько раз, всякий раз, когда меня заставляли отлаживать специфичные для платформы ошибки на платформах, отличных от Windows.

Проще говоря: Как отобразить строки Unicode (в кодировке UCS2) при отладке в Linux?

Теперь еще несколько деталей, которые я до сих пор выяснил. Наш Lib использует внутренне Unicode Строковый класс, который кодирует каждый символ как 16-битное значение Юникода (но мы не поддержка кодирования нескольких слов, поэтому мы в основном можем использовать только кодируемое подмножество UCS2 UTF16, но это все равно охватывает почти все используемые скрипты). Это уже ставит одну проблему, так как большинство платформ (т.е. linux / unix) учитывают wchar_t типы должны состоять из 4 байтов, тогда как в Windows это только 2 байта, таким образом Я не могу просто привести внутренний буфер строк к (wchar_t *), поэтому я не уверен, если это действительно поможет любому отладчику.

Для GDB Я понял, что я могу вызывать функции из отлаженного кода, чтобы печатать отладочные сообщения. Таким образом, я вставил специальную функцию в нашу библиотеку, который может произвольно преобразовать строковые данные и записать их в новый буфер. В настоящее время я транскодирую наш внутренний буфер в utf8, так как я ожидаю, что это быть наиболее вероятно, чтобы работать.

Но пока это решает проблему только частично: если строка латинская, тогда я теперь получаю читаемый вывод (тогда как нельзя напрямую печатать латиницу данные, если это 16-битный код), но я также должен иметь дело с другими сценариями (например, CJK (a.k.a. Hansi / Kanji), кириллица, греческий ...) Я должен специально отлаживать данные с помощью таких сценариев, так как используемые сценарии напрямую влиять на поток управления. Конечно, в этих случаях я вижу только те символы ISO, которые соответствуют байты, составляющие символ utf8, что делает отладку данных CJK еще более загадочные тогда правильно отображаемые строки будут.

Обычно GDB позволяет установить несколько кодировок хоста и цели, поэтому можно отправить правильный кодированный поток данных utf8 на консоль.

Но, конечно, я бы предпочел использовать IDE для отладки. В настоящее время я пытаюсь чтобы подружиться с Eclipse и CDT, но для отладки я также протестировал kdgb. В обоих приложениях я до сих пор мог получить только неправильно декодированные данные utf8. С другой стороны, я однажды отлаживал проект Java в Eclipse на платформе Windows. и все внутренние строки отображались правильно (но это приложение не было используя нашу lib и соответствующие строки), таким образом, по крайней мере, в некоторых ситуациях eclipse может правильно отображать символы Юникода.

Самым неприятным моментом для меня является то, что до сих пор я не мог даже придумать любое доказательство того, что отображение истинных данных Unicode (т.е. не ISO-символов) работает в любой установке в Linux (то есть, даже скрипты GDB для QStrings, которые я нашел, кажется чтобы отображать только латинские буквы и пропустить остаток), но, конечно, Кажется, почти каждое приложение Linux поддерживает данные Unicode, поэтому должны быть люди вокруг, которые отлаживают истинные данные Unicode на платформах Linux и я действительно не могу представить, что они все читают гекскоды вместо прямое отображение строк Юникода.

Таким образом, любые указатели на настройки, которые позволяют отладку строк Unicode, основаны для любых других строковых классов (например, QString) и / или IDE также приветствуется.

Ответы [ 4 ]

3 голосов
/ 12 ноября 2009

Большинство дистрибутивов Linux, как правило, имеют отличную поддержку Unicode. Однако я бы сказал, что использование UTF16 в Linux - ошибка. Я понимаю, что это было бы естественно, если исходить из среды Windows, но это только усложнит вам задачу в Linux.

Пока ваша локаль установлена ​​на Unicode, выводить строки UTF-32, (строки wchar_t), используя wprintf или wcout, тривиально, и, конечно, вы можете выводить строки UTF-8 с помощью обычных средств вывода. Тем не менее, с UTF-16 вы по сути ограничены созданием пользовательского строкового класса, который использует int16_t, который, как вы обнаружили, будет трудно распечатать в отладчике.

Вы упомянули, что создали функцию, которая переводит UTF-16 в UTF-8 для целей отладки, но символы переменной длины затрудняют работу. Почему бы просто не создать функцию, которая переводит UTF16 в UTF32, чтобы каждая кодовая точка Unicode представляла собой один символ? Таким образом, вы можете использовать вывод широких символов для чтения строк. GDB не позволяет вам выводить строки широких символов по умолчанию, но вы можете исправить это, используя этот простой скрипт .

3 голосов
/ 25 июня 2015

Простой скрипт "wchar.gdb", упомянутый Чарльзом Сальвией выше, помог мне, но через несколько лет его было трудно найти (ссылка в статье не работает), поэтому я вставлю его здесь. Скрипт также демонстрирует некоторые едва известные возможности макросов, встроенные в gdb.

define wchar_print
    echo "

    set $i = 0
    while (1 == 1)
            set $c = (char)(($arg0)[$i++])
            if ($c == '\0')
                    loop_break
            end
            printf "%c", $c
    end

    echo "\n
end


document wchar_print
wchar_print <wstr>
Print ASCII part of <wstr>, which is a wide character string of type wchar_t*.
end
0 голосов
/ 25 июня 2015

Текущие выражения GDB могут отображать 16-битные данные широких символов напрямую: Если ваша программа вообще не использует тип данных wchar_t (32 бит), например он использует библиотеки ICU (международные компоненты для Unicode) с широким типом данных UChar (16 бит), вы можете установить опцию gcc -fshort-wchar, определяя wchar_t и широкие литералы (L "abc", L'd ') как беззнаковые короткие (16 бит). Как следствие, никакие функции wchar_t glibc не должны вызываться. Если в целевой программе определена хотя бы одна фиктивная переменная wchar_t, GDB может отображать символьные данные wchar_t (16 бит). пример сеанса GDB:

short-wchar.c:
#include <wchar.h>
wchar_t wchr;
main() { printf("sizeof(L'a') = %d\n", sizeof(L'a')); return 0; }
gcc -g -fshort-wchar short-wchar.c -o short-wchar
# terminal session encoding utf-8 assumed
gdb short-wchar
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
    (gdb) show charset
    The host character set is "auto; currently UTF-8".
    The target character set is "auto; currently UTF-8".
    The target wide character set is "auto; currently UTF-32".
    (gdb) set target-wide-charset UTF-16
    (gdb) p L"Škoda"
    $1 = L"Škoda"
    (gdb) p (wchar_t*) (some UChar string)
    ....

Одной из причин использования 16-битного wchar_t на всех платформах является межплатформенная согласованность, см. ICU, OCI (Oracle Call Interface в широком режиме) и тип данных Java char.

0 голосов
/ 12 ноября 2009

Я полагаю, вы находитесь под X? Правильные ли шрифты установлены?

Если на консоли вы используете фрейм-буфер в качестве оконечного устройства? В режиме текстового режима VGA могут отображаться только 256/512 символов. (случай 512 iirc съедает немного цветового пространства)

...