在gcc

时间:2015-12-22 07:36:05

标签: string c++11 gcc

我的程序使用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,但我希望代码能够工作直到我这样做。

1 个答案:

答案 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时,这会被破坏。