我的程序使用std::string
,但是memmove
std :: string`实例。
直到gcc 5.1才能正常工作。
然而,这不再适用于gcc 5.3。我认为开发人员最终使用内部指针进行了SSO。
我肯定会解决这个问题,但有一些简单的方法可以用一些define或pragma来修复它吗?
代码与此类似:
// MyClass have std::string inside
MyClass *a = malloc(MAX * sizeof(MyClass));
// ...
// placement new on a[0]
// ...
memmove(&a[1], &a[0], sizeof(MyClass));
// ...
process(a[1]);
这是旧代码,请不要评论malloc
用法。
我将重构或切换到std::vector
,但我希望代码能够工作直到我这样做。
答案 0 :(得分:1)
您正在经历未定义行为的影响,但我想您知道这一点。您不能依赖于按字节方式复制非POD resp的效果。不是简单的可复制类型,编译器可以自由地改变这种行为。
我认为可以使用类作为参数为memmove
定义安全重载,并在其中使用copy-constructor。我不知道这是否严格合法,但您似乎在命名空间std
中使用C函数而不是C ++版本,所以至少您没有更改名称空间std
允许。
void memmove(MyClass* a, MyClass* b, size_t)
{
*a = *b;
}
严格来说,我认为这仍然是未定义的行为,因为C ++标准的17.6.4.3指定了
如果程序在上下文中声明或定义名称 保留,除非本条款明确允许,否则 行为未定义。
此外,C库中的所有名称都是保留名称,程序不得使用(17.6.4.3.2)。实际上,我认为这会奏效。
您可能需要使用-fno-builtin
进行编译,以防止gcc全局替换memmove
。如果覆盖该功能是非法的,您可以使用LD_PRELOAD
动态替换它。
这是一个黑客解决方案!您的代码可能仍然不起作用,因为编译器假设,当您memmove
它是POD / TriviallyCopyable对象并将其用于某些优化时,例如假设在memmove
之后,两个对象都由相同的字节表示。当您使用copy-constructor重新实现memmove
时,这会被破坏。