- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在我的 C++ 项目中使用 C 代码,我使用 extern "C"将其包括在内。然后,我在传递给 C 代码(使用 gcc 编译)的 C++ 类中定义结构。问题是,当该 C 代码访问在 C++ 类中定义的结构时,我得到了不同的对齐方式,并且代码读取和写入了错误的数据。这看起来很奇怪,但我已经调试了 3 个小时,基本上当我从 C++ 代码打印指向该结构的深层成员的指针时,一切都很好。但是如果我从 C 代码中打印指针,地址就不同了!
为什么会发生这种情况,我如何确保对齐一致?
(我通过重新编译所有内容来仔细检查这不是一个过时的编译问题。结果仍然相同。在 C 中,地址是 C++ 代码中报告的成员地址之前的 8 个字节)
编辑:问题在于 g++ 和 gcc 会以不同方式处理空结构。如果我的代码中有一个空的 struct foo {},那么在 g++ 下,我的结构的 sizeof 会大 1 个字节,并且成员的所有偏移量都会被弄乱。所以我将一个虚拟的 uint8_t 放入空结构中,这样它就不会再为空了,代码库中的所有此类问题似乎都消失了。现在对齐似乎工作相同并且结构大小也相同(对于每个空结构 g++ 以前会添加 1 个字节)。我不是 100% 确定 gcc 发生了什么,所以如果有人有任何要补充的,请随时告诉我这个
我的 gcc 版本是:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.5' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609
我在 gcc 下的编译标志是:
-std=gnu99 -Wchar-subscripts -Wformat -Wformat-nonliteral -Wformat-security -Wmissing-braces -Wparentheses -Wsequence-point -Wswitch -Wtrigraphs -Wno-unused-function -Wunused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wuninitialized -Wdiv-by-zero -Wfloat-equal -Wdouble-promotion -fsingle-precis
ion-constant -Wshadow -Wpointer-arith -Wwrite-strings -Wconversion -Wredundant-decls -Wunreachable-code -Winline -Wenum-compare -Wlong-long -Wchar-subscripts -Wextra -Werror -g -Os -ffunction-sections -fdata-sections -m32 -fstack-protector -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -ftest-coverage -fprofile-arcs
g++
-std=c++11 -Wextra -Werror -g -Os -ffunction-sections -fdata-sections -m32 -fstack-protector -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -ftest-coverage -fprofile-arcs
Edit2:将 -pedantic 添加到我的 cflags中,使 gcc 对空结构发出警告。之前放弃它是因为它破坏了许多其他东西和第三方 header (我们必须使用 -Werror)。幸运的是,诸如宏 ({}) 语句之类的东西可以以 __extension__ 为前缀,使它们通过 -pedantic。在代码库中还有其他一些需要更改的内容。还不知道在启用迂腐的情况下是否很难实现某些东西。有谁知道如何只对空结构启用警告或禁用迂腐不允许的某些特定内容?
最佳答案
正确的解决方案似乎是永远不要在将跨 C++ -> C 边界使用的代码中定义空结构。我有一个:
struct spinlock { }
针对单个处理器目标构建时,它是空的。所以 g++ 会生成这个 1 字节,而 gcc 只会丢弃它。因此,我的结构将具有不同的大小,offsetof 甚至会返回不同的结果,具体取决于代码是使用 gcc 还是 g++ 构建的。
所以我改成了
struct spinlock { uint8_t dummy; }
现在我的结构完全对齐并且一切正常,无需任何特殊的 C++ 标准规范。
关于c - GCC 和 G++ struct packing 的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48068142/
平时很少在jquery中用到this。查看代码时发现用到了,就调试出this的值,心想原来如此。还是挺有用的。这里总结一下this与$(this)的区别和使用。 $(this)生成的是什么?
使用单例类和应用程序范围的托管 bean 来保存应用程序数据有区别吗? 我需要查找某些 JNDI 资源,例如远程 bean 接口(interface),因此我为自己编写了一个单例来缓存我的引用并且只允
如果您仔细查看包含的图片,您会注意到您可以使用 Eclipse IDE 重构 Groovy 代码并将方法转换为闭包,反之亦然。那么,闭包到底是什么,它与方法有什么不同呢?有人可以举一个使用闭包的好例子
vagrant box repackage有什么区别( docs ) 和 vagrant package ( docs )? 我意识到 vagrant package仅适用于 VirtualBox 提
我想看看是否有人可以解释为什么以下代码适用于 valueOf 但不适用于其他代码。 import java.math.BigDecimal; public class Change { publ
这个问题已经有答案了: 已关闭12 年前。 Possible Duplicates: What is Closures/Lambda in PHP or Javascript in layman te
This question already has answers here: Vagrant, Docker, Puppet, Chef (3个答案) 2年前关闭。 docker和chef有什么共同
以下代码在95%的机器上产生相同的输出,但是在几台机器上却有所不同。在 Debug模式下,输出: Changing from New to Fin OK 但在 Release模式下: Changing
////Creating Object var Obj; // init Object Obj= {}; 它们之间有什么区别两个? 有没有可能把它变成一个单行? 这样使用有什么好处吗?
我想找出定时器服务之间的区别。我应该使用哪个以及何时使用。我正在使用 Jboss 应用服务器。 1) java.ejb.Schedule。 @Schedule注解或配置自xml。 2) javax.e
我发现在 C++ 中可以通过三种不同的方式将对象传递给函数。假设我的类(class)是这样的: class Test { int i; public: Test(int x);
有什么区别。 public class Test { public static void main(String args[]) { String toBeCast = "c
如果我有一列,设置为主索引,设置为INT。 如果我不将其设置为自动递增,而只是将唯一的随机整数插入其中,与自动递增相比,这是否会减慢 future 的查询速度? 如果我在主索引和唯一索引为 INT 的
这两种日期格式有什么区别。第一个给出实际时间,第二个给出时间购买添加时区偏移值。 NSDateFormatter * dateFormatter = [[NSDateFormatter alloc]
如果有一个函数,请说foo: function foo() { console.log('bar'); } 那么在 JavaScript 中,从另一个函数调用一个函数有什么区别,如下所示: f
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 4 年前。 Improv
代码是什么: class Time { private: int hours; int minutes; int seconds; pu
我知道这是非常基本的,但有人介意解释一下这两个数组声明之间的区别吗: #include array myints; ...和: int myints[5]; ...以及为什么 myints.size
我学会了如何根据 http://reference.sitepoint.com/css/specificity 计算 css 特异性但是,基于this reference,我不明白伪类(来自c)和伪元
为什么在运行 2) 时会出现额外的空行?对我来说 1 就像 2。那么为什么 2) 中的额外行? 1) export p1=$(cd $(dirname $0) && pwd) #
我是一名优秀的程序员,十分优秀!