Boost.Interprocess:如果使用或不使用优化(GCC)编译,测试用例会给出不同的结果
在进行优化编译时,我在 Boost.Interprocess 分配器方面遇到了一些麻烦。我设法将其缩减为 40 行测试用例,其中大部分是样板文件。只需看一下下面代码中的 create()
和 main()
函数即可。
#include <iostream>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
namespace interp = boost::interprocess;
struct interp_memory_chunk
{
interp::managed_shared_memory chunk;
interp_memory_chunk ()
{
interp::shared_memory_object::remove ("GCC_interprocess_test");
chunk = interp::managed_shared_memory (interp::create_only, "GCC_interprocess_test", 0x10000);
}
~interp_memory_chunk ()
{
interp::shared_memory_object::remove ("GCC_interprocess_test");
}
};
typedef interp::allocator <int, interp::managed_shared_memory::segment_manager> allocator_type;
inline void
create (allocator_type& allocator, allocator_type::value_type& at, int value)
{
allocator.construct (allocator.address (at), value);
}
int
main ()
{
interp_memory_chunk memory;
allocator_type allocator (memory.chunk.get_segment_manager ());
allocator_type::pointer data = allocator.allocate (1);
create (allocator, *data, 0xdeadbeef);
std::cout << std::hex << *data << "\n";
}
当编译此而不优化:
g++ interprocess.cpp -lboost_thread -o interprocess
并运行时,输出为deadbeef
,正如预期的那样。
然而,当编译优化时:
g++ -O1 interprocess.cpp -lboost_thread -o interprocess
运行给出0
,不是预期的结果。
所以,我不确定问题出在哪里。这是我的程序中的错误吗?即我是否调用某些 UB?这是 Boost.Interprocess 中的错误吗?或者也许在海湾合作委员会?
根据记录,我在 GCC 4.6 和 4.5 中观察到了这种行为,但在 GCC 4.4 或 Clang 中没有观察到这种行为。这里的Boost版本是1.46.1。
编辑:请注意,将 create()
作为单独的函数至关重要,这可能表明当 GCC 内联它时会出现问题。
I'm having some troubles with Boost.Interprocess allocators when compiling with optimization. I managed to get this down to a 40 lines testcase, most of which is boilerplate. Just have a look at create()
and main()
functions in the code below.
#include <iostream>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
namespace interp = boost::interprocess;
struct interp_memory_chunk
{
interp::managed_shared_memory chunk;
interp_memory_chunk ()
{
interp::shared_memory_object::remove ("GCC_interprocess_test");
chunk = interp::managed_shared_memory (interp::create_only, "GCC_interprocess_test", 0x10000);
}
~interp_memory_chunk ()
{
interp::shared_memory_object::remove ("GCC_interprocess_test");
}
};
typedef interp::allocator <int, interp::managed_shared_memory::segment_manager> allocator_type;
inline void
create (allocator_type& allocator, allocator_type::value_type& at, int value)
{
allocator.construct (allocator.address (at), value);
}
int
main ()
{
interp_memory_chunk memory;
allocator_type allocator (memory.chunk.get_segment_manager ());
allocator_type::pointer data = allocator.allocate (1);
create (allocator, *data, 0xdeadbeef);
std::cout << std::hex << *data << "\n";
}
When compiling this without optimization:
g++ interprocess.cpp -lboost_thread -o interprocess
and running, the output is deadbeef
, as expected.
However, when compiling with optimization:
g++ -O1 interprocess.cpp -lboost_thread -o interprocess
running gives 0
, not what is expected.
So, I'm not sure where the problem is. Is this a bug in my program, i.e. do I invoke some UB? Is it a bug in Boost.Interprocess? Or maybe in GCC?
For the record, I observe this behavior with GCC 4.6 and 4.5, but not with GCC 4.4 or Clang. Boost version is 1.46.1 here.
EDIT: Note that having create()
as a separate function is essential, which might indicate that problem arises when GCC inlines it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
正如其他人所建议的,一种解决方案是尝试找到触发问题所需的最小优化标志集,使用 -O1 -fno...
其他选项:
使用 Valgrind 并查看它会产生什么结果
尝试使用“-fdump-tree-all”进行编译,这会生成一堆中间编译文件。然后您可以查看编译后的代码是否有任何差异。这些中间文件仍然是C++语言,所以你不需要了解汇编程序。它们几乎是人类可读的,并且肯定是可比较的。
As others have suggested, one solution is try to find the minimial set of optimisation flags you need to trigger your problem, using -O1 -fno....
Other options:
Use Valgrind and see what it comes up with
Try compiling with "-fdump-tree-all", this generates a bunch of intermediate compiled files. You can then see if the compiled code has any differences. These intermediate files are still in C++, so you don't need to know assembler. They are pretty much human readable, and certainly diffable.