gpt4 book ai didi

c++ - 放置新的唯一指针

转载 作者:搜寻专家 更新时间:2023-10-31 01:32:12 25 4
gpt4 key购买 nike

这是我的第一篇文章。我希望它包含正确的、最少的信息。如果我遗漏了什么,请告诉我。

我正在尝试使用 placement new 来提高以下代码块的效率(我想减少内存分配调用的次数,因为 number_of_actions 变量很大(> 500k)) .

首先,我使用了两个类,它们的关系可以概括为:

class txn {
public:
int i;
txn(): i(0) {};
};

class ActionClass {
private:
txn* t;
public:
ActionClass(txn* t): t(t) {};
~ActionClass() { delete t; }
};

我最初用来创建对象指针数组的代码:

std::vector<std::unique_ptr<IBatchAction>> allocate_actions(unsigned int number_of_actions) {
std::vector<std::unique_ptr<IBatchAction>> res;
for (unsigned int i = 0; i < number_of_actions; i++) {
// construct the action
std::unique_ptr<IBatchAction> act = std::make_unique<ActionClass>(new TestTxn());

res.push_back(std::move(act));
}
return res;
}

更改为使用 placement new 后的代码:

std::vector<std::unique_ptr<IBatchAction>> allocate_actions(unsigned int number_of_actions) {
std::vector<std::unique_ptr<IBatchAction>> res(number_of_actions);

// allocate all of the memory for actions up front to amortize the cost.
ActionClass* actions =
reinterpret_cast<ActionClass*>(new char[number_of_actions * sizeof(ActionClass)]);
txn* txns = reinterpret_cast<txn*>(new char[number_of_actions * sizeof(TestTxn)]);

// use placement new to initialize actions and assign them to unique_ptrs
for (unsigned int i = 0; i < number_of_actions; i++) {
// construct the action using placement new from the memory allocated above.
res[i].reset(new(&(actions[i])) ActionClass(new(&(txns[i])) TestTxn()));
}
return res;
}

在 main.cpp 中,我只是多次调用上述函数,计时并返回 0。从上述函数返回的 vector 在循环迭代之间被销毁。结果,我在段错误之前得到了以下堆栈跟踪:

#0  std::unique_ptr<IBatchAction, std::default_delete<IBatchAction> >::~unique_ptr (
this=<optimized out>, __in_chrg=<optimized out>) at /usr/include/c++/5/bits/unique_ptr.h:236
#1 std::_Destroy<std::unique_ptr<IBatchAction, std::default_delete<IBatchAction> > > (
__pointer=<optimized out>) at /usr/include/c++/5/bits/stl_construct.h:93
#2 std::_Destroy_aux<false>::__destroy<std::unique_ptr<IBatchAction, std::default_delete<IBatchAction> >*> (__last=<optimized out>, __first=0x7ffff7f06018)
at /usr/include/c++/5/bits/stl_construct.h:103
#3 std::_Destroy<std::unique_ptr<IBatchAction, std::default_delete<IBatchAction> >*> (
__last=<optimized out>, __first=<optimized out>) at /usr/include/c++/5/bits/stl_construct.h:126
#4 std::_Destroy<std::unique_ptr<IBatchAction, std::default_delete<IBatchAction> >*, std::unique_ptr<IBatchAction, std::default_delete<IBatchAction> > > (__last=0x7ffff7fc9510,
__first=<optimized out>) at /usr/include/c++/5/bits/stl_construct.h:151
#5 std::vector<std::unique_ptr<IBatchAction, std::default_delete<IBatchAction> >, std::allocator<std::unique_ptr<IBatchAction, std::default_delete<IBatchAction> > > >::~vector (this=0x7fffffffd910,
__in_chrg=<optimized out>) at /usr/include/c++/5/bits/stl_vector.h:424
#6 time_workload_creation (exp_conf=...) at start_batch/main.cc:18
#7 0x000000000040320c in main (argc=<optimized out>, argv=<optimized out>)
at start_batch/main.cc:44

我不熟悉展示位置的概念。以下是我用来编写上述代码的内容:

  1. Can I use placement new to reset an object within a shared_ptr? -- 使用 reset 分配使用 placement new 创建的新对象
  2. placement new on shared_ptr make seg fault when delete ——一个非常相似的问题。这个问题的答案对我完全有帮助:(

我可能做了一些明显错误的事情,但我无法弄清楚。帮助?如果您需要来自 main(简化)的实际代码,就在这里(actions.h 包含我已经讨论过的函数)。

#include "actions.h"

#include <chrono>
#include <vector>

void time_workload_creation(unsigned int act_num) {
std::chrono::system_clock::time_point time_start, time_end;
std::vector<double> results;
for (unsigned int i = 0; i < 10; i++) {
time_start = std::chrono::system_clock::now();
auto workload = allocate_actions(act_num);
time_end = std::chrono::system_clock::now();
results.push_back(
std::chrono::duration_cast<std::chrono::milliseconds>(time_end - time_start).count());
}

for (unsigned int i = 0; i < 10; i++) {
std::cout << i << "\t\t" <<
act_num << "\t\t" <<
results[i] << "\t\t" <<
act_num / results[i] << std::endl;
}
};

int main(int argc, char** argv) {
time_workload_creation(1000000);
return 0;
}

编译使用:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)

最佳答案

Code after changing to use placement new:
[...]

此代码具有未定义的行为。您使用 new[] 创建一个 char 数组,然后重置 N 个 unique_ptr 对象,这将尝试删除 N 个不同的 ActionClass对象。你希望它如何工作?您需要使用 delete[] 来释放 char 数组,而不是对 char 数组的 block 使用 N delete 操作。

同样,每个 ActionClass 都会尝试delete 它的 txn 对象,但这也是完全未定义的,因为你没有分配 N txn 对象,你分配了另一个 char 数组。

这不是内存分配的工作方式。您不能先分配一大块,然后再释放其中的一部分。 (好吧,你可以,但只能通过编写你自己的自定义(取消)分配函数或分配器)。

关于c++ - 放置新的唯一指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43722222/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com