Qt:更新QString

时间:2018-09-19 22:06:53

标签: c++ qt qt5 qstring

我正在修改用Qt(LibrePilot)编写的GUI代码。有一种添加用户类的方法。它们是根据XML描述自动生成的。

所以这个课:

<xml>
<object name="RecorderService_RecordDescription" singleinstance="true" settings="false" category="State">
    <description>For Recorder gadget</description>

    <field name="text"      units="char"   type="string"  elements="1"/>

    <access gcs="readwrite" flight="readwrite"/>
    <telemetrygcs    acked="false" updatemode="manual"   period="0"/>
    <telemetryflight acked="false" updatemode="periodic" period="1000"/>
    <logging                       updatemode="periodic" period="100"/>
</object>
</xml>

将自动生成为一个类,该类具有一个包含在结构内部的数据元素,并带有访问该数据元素的方法。

// Field structure
typedef struct {
    QString text;

} __attribute__((packed)) DataFields;

当我尝试使用text方法将setText设置为新值时:

void RecorderService_RecordDescription::setText(const QString value)
{
   mutex->lock();
   bool changed = (data_.text != static_cast<QString>(value));
   data_.text = static_cast<QString>(value);
   mutex->unlock();
   if (changed) { emit textChanged(value); }
}

我得到SIGABRT例外。

#0  0x00007ffff509ce97 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff509e801 in __GI_abort () at abort.c:79
#2  0x00007ffff50e7897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff5214b9a "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007ffff50ee90a in malloc_printerr (str=str@entry=0x7ffff5212d88 "free(): invalid pointer") at malloc.c:5350
#4  0x00007ffff50f5e1c in _int_free (have_lock=0, p=0x7ffff5f8c5f0, av=0x7ffff5449c40 <main_arena>) at malloc.c:4157
#5  0x00007ffff50f5e1c in __GI___libc_free (mem=0x7ffff5f8c600) at malloc.c:3124
#6  0x00007fffc798671e in RecorderService_RecordDescription::setText(QString) () at /usr/lib/librepilot-gcs/plugins/LibrePilot/libUAVObjects.so

我发现的一个解决方案是,如果我向RecorderService_RecordDescription添加另一个字段。即XML是这样的:

<xml>
<object name="RecorderService_RecordDescription" singleinstance="true" settings="false" category="State">
    <description>For Recorder gadget</description>

    <field name="text"      units="char"   type="string"  elements="1"/>
    <field name="seconds"   units="sec"    type="uint32"  elements="1"/>

    <access gcs="readwrite" flight="readwrite"/>
    <telemetrygcs    acked="false" updatemode="manual"   period="0"/>
    <telemetryflight acked="false" updatemode="periodic" period="1000"/>
    <logging                       updatemode="periodic" period="100"/>
</object>
</xml>

错误消失了。自动生成的类具有以下数据结构:

// Field structure
typedef struct {
    quint32 seconds;
    QString text;

} __attribute__((packed)) DataFields;

setText的代码是相同的。 在使用旧版gcc之前,没有发生此错误。当前版本是7.2。

任何人都知道为什么会发生错误以及如何优雅地修复它。 谢谢。

1 个答案:

答案 0 :(得分:0)

代码自动生成的事实与问题无关。您的意思是,您有一个非常短的代码片段,据说该片段失败了:将其移动到单独的main.cpp作为测试用例!我敢打赌,您在代码中还有其他问题,这就是为什么它会失败。您遇到的问题之一是__attribute__((packed))本质上是请编译器提供一些未定义的行为-您不需要该属性,因为它的工作方式并非您认为的工作方式。正确实现此属性不应生成成员对齐不充分的记录,因此可能仍添加了特定于平台的填充-您只是假设不会。而且无论如何:QString并不是可以转储到磁盘的东西,因此打包此结构没有任何意义。在某些情况下,Gcc错误地实现了此属性,这可能会导致您观察到的行为,尽管在显示的结构的特定情况下并非如此。可能其他一些压缩结构最终破坏了程序状态并导致了崩溃。首先:制作一个独立的测试用例。然后我们可以找出问题所在。但是,最重要的是:请勿使用__attribute__((packed)。它的典型用法是:序列化。如果要对二进制数据进行序列化/反序列化,请使用QDataStream或类似的机制。