这是我的第一篇帖子。我希望它包含正确的,最少的信息。如果我遗漏了任何内容,请告诉我。
我正在尝试使用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;
}
更改为使用展示位置后的代码:
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.从上面的函数返回的向量在循环迭代之间被销毁。结果我在segfault之前获得了以下堆栈跟踪:
#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
我对放置新概念不熟悉。以下是我用来编写上述代码的内容:
我可能会做一些明显错误的事情,但我无法弄清楚。救命?如果你需要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版本5.4.0 20160609(Ubuntu 5.4.0-6ubuntu1~16.04.4)
答案 0 :(得分:3)
更改为使用展示位置后的代码新:
[...]
此代码具有未定义的行为。您使用<rewrite>
<rules>
<clear />
<rule name="Force WWW and SSL" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="^[^www]" />
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://www.sysadmit.com/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
创建char
数组,然后重置N new[]
个对象,这些对象将尝试删除N个不同的unique_ptr
个对象。你怎么期望这个工作?您需要使用ActionClass
释放char数组,而不是在delete[]
数组的块上使用N delete
个操作。
同样,每个char
会尝试ActionClass
其delete
个对象,但这也是完全未定义的,因为您没有分配N {{1}你分配了另一个txn
数组。
这不是内存分配的工作原理。你不能分配一个大块然后解除分配它。 (嗯,你可以,但只能编写自己的自定义(de)分配函数或分配器)。