我正在为我们的项目检查其他人的C++代码,该代码使用MPI实现高性能计算(10^5-10^6核)。该代码旨在允许(潜在)不同计算机在不同体系结构上进行通信。他写了一篇评论,大意是:
我们通常使用
new和delete,但这里我使用的是malloc和free。这是必要的,因为一些编译器在使用new时会以不同的方式填充数据,从而导致在不同平台之间传输数据的错误。malloc不会出现这种情况。
这不符合我从标准new和malloc问题中知道的任何东西。
新/删除和malloc/free有什么区别?暗示编译器可以以不同的方式计算对象的大小(但是为什么这与使用sizeof不同呢?)
malloc &新的和新的是一个相当流行的问题,但只讨论使用构造函数的new,而malloc不使用构造函数,这与此无关。
malloc如何理解对齐?说,内存可以保证与new或malloc正确地对齐,这正是我之前所想的。
我的猜测是,在过去的一段时间里,他对自己的错误进行了错误诊断,并推断出new和malloc提供了不同数量的填充,我认为这可能不是真的。但我在谷歌或之前的任何问题中都找不到答案。
帮帮我,StackOverflow,你是我唯一的希望!
发布于 2012-11-08 11:39:24
有一点是挑剔的。malloc保证返回与任何标准类型对齐的地址。::operator new(n)只保证返回对任何不大于n的标准类型对齐的地址,如果T不是字符类型,则只需要new T[n]返回对齐T的地址。
但是,这只有在您使用特定于实现的技巧时才有意义,比如使用指针的底部几个位来存储标志,或者以其他方式依赖地址来进行比严格需要的更多的对齐。
它不会影响对象中的填充,不管如何分配内存,对象的布局都必须完全相同。因此,很难看出这种差异如何会导致数据传输错误。
该评论的作者对堆栈上的对象或全局中的对象有何看法?在他看来,这些对象是“像malloc那样的填充”还是“新的填充”?这可能会为这个想法的来源提供线索。
也许他很困惑,但也许他所说的代码不仅仅是malloc(sizeof(Foo) * n)和new Foo[n]之间的直接区别。也许更像是:
malloc((sizeof(int) + sizeof(char)) * n);与
struct Foo { int a; char b; }
new Foo[n];也就是说,也许他说的是“我使用malloc",但意思是”我手动将数据打包到未对齐的位置,而不是使用struct“。实际上,不需要malloc来手动打包结构,但是没有意识到这是一个较小程度的混乱。有必要定义通过导线发送的数据布局。当使用结构时,不同的实现将以不同的方式填充数据。
发布于 2012-11-08 10:36:33
您的同事可能已经想到了new[]/delete[]的神奇曲奇(这是实现在删除数组时使用的信息)。但是,如果使用new[]返回的地址开始的分配(而不是分配器),这将不会是一个问题。
包装似乎更有可能。ABI中的变化可能(例如)导致在结构末尾添加不同数量的尾随字节(这受对齐性的影响,也考虑数组)。使用malloc,结构的位置可以指定,因此更容易移植到国外的ABI。这些变化通常是通过指定转换结构的对准和包装来防止的。
发布于 2012-11-08 10:06:53
我想你是对的。填充是由编译器完成的,而不是new或malloc。即使您声明一个数组或结构而不使用new或malloc,填充注意事项也会适用。在任何情况下,虽然我可以看到new和malloc的不同实现在不同平台之间移植代码时是如何造成问题的,但我完全看不出它们如何导致在平台间传输数据的问题。
https://stackoverflow.com/questions/13286706
复制相似问题