c++ - 在 Visual Studio C++ 中初始化 std::string 数组时崩溃

标签 c++ string visual-studio new-operator

问题:我正在尝试为 std::string 数组分配内存,然后使用 new(...)[]() 对其进行初始化.然后我尝试为数组元素赋值,这导致应用程序崩溃(访问冲突)。问题是:我是否遗漏了一些编译器标志或一些明显的东西?

编译这个
cl.exe /DEBUG /EHsc /MTd /Zi test.cc

生成崩溃的可执行文件(在 VS 2017 和 VS 2012 中测试)。附带说明一下,它在带有 GCC 的 Linux 上按预期工作。

#include <iostream>
#include <string>

struct S {
  int a,b;
  S() : a(99), b(299) {}
  S & operator=(const char * rhs) { a = 100; b = 300; return *this; }  
};
std::ostream & operator<<(std::ostream & os, const S & s) { os << "(" << s.a << "," << s.b << ")"; return os; }  


typedef std::string T;
//typedef S T;
int main(int argc, char ** argv) {
    size_t N = 100;
    std::allocator<T> mem;
    T * data = mem.allocate(N);
    new(data)T[N]();

    for (ptrdiff_t i = 0; i < N; ++i)
        data[i] = "HELLO WORLD";
    for (ptrdiff_t i = 0; i < N; ++i)
        std::cout << data[i] << std::endl;
}

我尝试使用其他 typedef,在这种情况下,初始化工作完全符合预期。

编辑:如果我使用 C calloc 而不是 std::allocator 进行分配,我会看到同样的崩溃。

已解决。原来问题是这样的:C++标准说new T[N]表达式分配至少 sizeof(T)*N 字节。 Visual C 分配额外的开销。放置 new new(ptr)T[N] 假定额外开销在 ptr 中可用。 以下答案的解决方案是分别循环和构造每个项目。

最佳答案

问题在于此处描述的未指定开销:Array placement-new requires unspecified overhead in the buffer?

快速修复是

#include <iostream>
#include <string>

struct S {
  int a,b;
  S() : a(99), b(299) {}
  S & operator=(const char * rhs) { a = 100; b = 300; return *this; }  
};
std::ostream & operator<<(std::ostream & os, const S & s) { os << "(" << s.a << "," << s.b << ")"; return os; }  


typedef std::string T;
//typedef S T;
int main(int argc, char ** argv) {
    size_t N = 100;
    std::allocator<T> mem;
    T * datastor = mem.allocate(N+1);
    T * data = new(datastor)T[N]();

    for (ptrdiff_t i = 0; i < N; ++i)
        data[i] = "HELLO WORLD";
    for (ptrdiff_t i = 0; i < N; ++i)
        std::cout << data[i] << std::endl;
}

但这并不能保证总是有效,因为“未指定的开销”理论上可能大于 sizeof(std::string)

没有未指定行为的版本将单独更新元素,如下所示:

#include <iostream>
#include <string>

struct S {
  int a,b;
  S() : a(99), b(299) {}
  S & operator=(const char * rhs) { a = 100; b = 300; return *this; }  
};
std::ostream & operator<<(std::ostream & os, const S & s) { os << "(" << s.a << "," << s.b << ")"; return os; }  


typedef std::string T;
//typedef S T;
int main(int argc, char ** argv) {
    size_t N = 100;
    std::allocator<T> mem;
    T * data = mem.allocate(N);
    for (ptrdiff_t i = 0; i < N; ++i)
        new(&data[i]) T();
    for (ptrdiff_t i = 0; i < N; ++i)
        data[i] = "HELLO WORLD";
    for (ptrdiff_t i = 0; i < N; ++i)
        std::cout << data[i] << std::endl;
    for (ptrdiff_t i = 0; i < N; ++i)
        data[i].~T();
    mem.deallocate(data, N);
}

关于c++ - 在 Visual Studio C++ 中初始化 std::string 数组时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44674800/

相关文章:

c++ - 从 char 字符串转换为 uint8_t 数组?

C++ 前向声明(指针)- 访问成员

string - 如何将Vec <char>转换为字符串

JavaScript 字符串操作

javascript - 从javascript中断在Razor View中调用data-url-action

c++ - 指向 C++ 类成员函数的指针作为全局函数的参数?

c++ - 使用 CRT 库查找特定的内存泄漏

c - 复制结构中包含的字符串指针时出现问题

c++ - 是否可以禁用编译器警告 C4503?

git - Visual Studio Git 错误 : "The index is locked. This might be due to a concurrent or crashed process."