C 如何修复传递给pango_layout_set_text()的无效UTF-8字符串

C 如何修复传递给pango_layout_set_text()的无效UTF-8字符串,c,gtk,gtk3,pango,C,Gtk,Gtk3,Pango,我从使用gtk+的应用程序中得到以下警告: (foo:11333): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text() 发出警告的功能如下: static void show_error(GtkWindow *parent, const gchar *fmt, ...) { GtkWidget *dialog; va_list args; va_start(args,fmt); d

我从使用gtk+的应用程序中得到以下警告:

(foo:11333): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()
发出警告的功能如下:

static void show_error(GtkWindow *parent, const gchar *fmt, ...)
{
  GtkWidget *dialog;
  va_list args;

  va_start(args,fmt);
  dialog = gtk_message_dialog_new(parent,
                  GTK_DIALOG_DESTROY_WITH_PARENT,
                  GTK_MESSAGE_ERROR,
                  GTK_BUTTONS_OK,
                  fmt,
                  args);

  (void)gtk_dialog_run(GTK_DIALOG(dialog));

  gtk_widget_destroy(dialog);
  va_end(args);
}
我正在调用
ui\u show\u error(窗口,“error cannot read file%s”,文件名)

其中,
filename
是以null结尾的字符串,这对
str*()
*printf()
函数族很好


如何修复此问题?

不可能以这种方式链接VAU列表参数。看见现在发生的是
gtk_message_dialog_new
正在将va_list参数(它有一些编译器定义的格式)解释为指向字符串的指针,因此您得到的是垃圾。由于没有接受va列表的消息对话框函数,因此您唯一的选择是使用vsprintf或类似的glib函数之一构建字符串,并将其作为一个参数以“%s”格式传递给
gtk\u message\u dialog\u new


为了在未知格式字符串面前构建字符串,通常的技术是使用一种“n”变体,如带有较大缓冲区的
vsnprintf
,如果发生截断,则增加缓冲区大小并重新执行。但是,glib有
g_vasprintf()
,它为您分配缓冲区。它还具有
g\u printf\u string\u upper\u bound()
,可用于根据格式字符串调整缓冲区的大小。

在Linux从头开始(LFS)的构建中,我正好遇到了这个问题。 问题是影响JavaSwing接口文本输入、gdk接口文本输入,有时会默默地忽略输入,就像文本字段被禁用一样。 原因是没有任何UTF8区域设置。 就我而言:

$ locale -a
C
POSIX
pt_BR
pt_BR.iso88591
因此,为了解决这个问题,我定义了一个新的语言环境类型utf8,如:

localedef -i pt_BR -f UTF-8 pt_BR.UTF-8

此后,一切都变得有用,不再发出警告。至少在我的例子中。

OP没有显示实际的字符串,ui\u show\u error函数在哪里? 什么Gtk+版本?默认情况下,gtk_消息_对话框_新的“使用标记”属性为 错,那么这篇文章有什么遗漏吗

你可以这样做:

msg = g_vasprintf(fmt, args);

if (strstr(msg, "</"))
  msg_has_markup = TRUE;

dialog = g_object_new (GTK_TYPE_MESSAGE_DIALOG,
                       "message-type",         GTK_MESSAGE_ERROR,
                       "text",                 msg,
                       "use-markup",           msg_has_markup,
                       "buttons",              GTK_BUTTONS_OK,
                        NULL);
g_free (msg);
msg=g_vasprintf(fmt,args);

如果(strstr)(msg,“您确定文件名是严格的ASCII吗?可能是包含了违反UTF-8的内容。据我所知,printf()不关心UTF-8,也许这就是它不抱怨的原因是,请参阅
const char*s=“foo”;show_error(NULL,%s baa”,s)
我收到了相同的警告消息。可能是在调用show_error()之前发生的?您应该检查用于创建GTK对话框的所有字符串是否100%确定否。它发生在
show_error()处
call。我编写了一个单独的文件进行调试,我使用的代码与我在评论中发布的代码相同,并给出了相同的警告。我的默认语言不是英语,并且包含重音符号。有什么关系吗?简单的事情如下:
show\u error(NULL,“one:%d”,1)
给我负的随机值;类似这样的值
one:-1079463944
就像我在访问随机内存一样。一个没有正确终止的字符串也可能有垃圾字符触发此警告。