我对在c ++中使用指针/ smartpointer感到困惑。 我们想从NIC捕获数据包。我们使用PF_RING ZC来捕获数据包,如下所示:
typedef folly::ProducerConsumerQueue<std::string> ZCTask;
typedef boost::shared_ptr<ZCTask> ZCTask_ptr;
void runZCConnection() {
ZCTask_ptr activeBufferConnection(new folly::ProducerConsumerQueue<std::string>(200000));
LOG_INFO("capture_loop for connections: Entering >> SHARE POINTER .");
int h = 0;
for (;;) {
if (likely(pfring_zc_recv_pkt(zqc, &buffer_connection, _wait_for_packet) >= 0)) {
u_char *pkt_data = pfring_zc_pkt_buff_data(buffer_connection, zqc);
std::string payload(pkt_data + _ConnectionHeaderSize, pkt_data + _snapLengthConnection);
if (activeBufferConnection->isFull()) {
LOG_INFO("ZC Active buffer Connction is full");
_buffersConnection.add(activeBufferConnection);
LOG_INFO(">> after add. USAGEG %ld", activeBufferConnection.use_count());
activeBufferConnection.reset(new folly::ProducerConsumerQueue<std::string>(200000));
LOG_INFO(">> after reset. USAGEG %ld", activeBufferConnection.use_count());
folly::ProducerConsumerQueue<std::string>(_bufferSizeConnection + 1);
if (h++ > 25) {
break;
}
}
activeBufferConnection->write(payload);
continue;
}
}
for (int a = 0; a < 25; a++) {
//get new task
Node* node = _buffersConnection.get2();
{
ZCTask_ptr zcTaskConnection = node->Data;
delete node;
node = NULL;
LOG_INFO(">> After node delete. USAGEG %ld",
LOG_INFO("connection buffer : %d", a);
}
}
LOG_INFO("delete");
} //packet consumer
可以看出,首先我们将数据包存储在runZCWrapper中的folly SPMC队列中。当队列已满时,将写入名为_ buffersConnection的链接列表。
捕获工作正常,我们保存所有数据包。这种代码和平的问题在于它的高内存消耗。当打包到达时,activeBufferConnection会存储它。当数据包数量增加到1000000时,创建新的activeBufferConnection并将最后一个存储在名为buffersconnections的链接列表中。我们将buffersconnections的数量设置为25。
从上面的代码和平中可以看出,我们正在使用智能指针 指向activeBufferConnection。当activeBufferConnection已满时,其指针传递给buffersconnections的“add”方法。
以下是我们在runZCConnection中使用的ArchiveList类的一些代码;
class ArchiveList {
typedef folly::ProducerConsumerQueue<std::string> ZCTask;
typedef boost::shared_ptr<ZCTask> ZCTask_ptr;
private:
Node* root;Node* last;
std::mutex mutex_;
std::condition_variable cond_;
public:
ArchiveList() {
root = new Node();
last = root;
}
Node*
get2() {
std::unique_lock<std::mutex> mlock(mutex_);
while (root->Next == NULL) {
LOG_INFO("get null");
cond_.wait(mlock);
}
LOG_INFO("1");
Node* toDelete = root->Next;
LOG_INFO("1");
root->Next = toDelete->Next;
LOG_INFO("1");
return toDelete;
}
void
add(ZCTask_ptr item) {
std::unique_lock<std::mutex> mlock(mutex_);
Node* newItem = new Node();
newItem->Data = item;
newItem->Prev = last;
last->Next = newItem;
last = newItem;
mlock.unlock();
cond_.notify_one();
LOG_INFO("+");
}
};
当activeBufferConnection的数量增加到25时,第一个循环结束,第二个循环开始工作。第二个循环删除链接列表的所有25个元素。 以下是我们的Node类的一些代码,用于runZCConnection;
class Node {
public:
typedef folly::ProducerConsumerQueue<std::string> ZCTask;
typedef boost::shared_ptr<ZCTask> ZCTask_ptr;
Node() {
Next = NULL;Prev = NULL;Data = NULL;
}
~Node() {
Next = NULL;Prev = NULL;
LOG_INFO(" >> NODE DCTOR. USAGEG %ld", Data.use_count());
Data.reset();
LOG_INFO("NODE DCTOR");
}
ZCTask_ptr Data;
Node* Next;
Node* Prev;
private:
};
top命令的输出是问题所在。 runZCConnection的第一个循环在一些缓冲区上存储数据包。删除其secound循环上的缓冲区后,它们使用的内存不会被释放,我们不知道为什么会发生这种情况。
CPU MEM
83698 root 49.3 0.3 0:01.49 ng4-m2
83698 root 39.1 0.6 0:02.67 ng4-m2
83698 root 41.5 0.8 0:03.92 ng4-m2
83698 root 1.3 1.0 0:05.49 ng4-m2
83698 root 1.0 1.0 0:05.52 ng4-m2
83698 root 1.7 0.9 0:05.57 ng4-m2
如上面的命令所示,程序删除所有缓冲区后,内存不会被释放。问题可能与错误删除缓冲区有关,也可能与错误使用指针有关。我们在代码的某些位置设置了一些日志,这些日志返回有关程序及其指针状态的一些信息。 以下是一些输出行:
INFO | ZCWrapper.hpp | runZCConnection:260 : ZC Active buffer Connction is full
INFO | ArchiveList.h | add:80 : +
INFO | ZCWrapper.hpp | runZCConnection:262 : >> after add. USAGEG 2
INFO | ZCWrapper.hpp | runZCConnection:264 : >> after reset. USAGEG 1
.
.
.
INFO | ArchiveList.h | get2:56 : 1
INFO | Node.hpp | ~Node:27 : >> NODE DCTOR. USAGEG 2
INFO | Node.hpp | ~Node:29 : NODE DCTOR
INFO | ZCWrapper.hpp | runZCConnection:286 : >> After node delete. USAGEG 1
INFO | ZCWrapper.hpp | runZCConnection:308 : >> END OF ONE TASK. USAGEG 0
INFO | ZCWrapper.hpp | runZCConnection:310 : connection buffer : 1
.
.
.
INFO | ZCWrapper.hpp | runZCConnection:315 : delete
我们如何解决问题? 在此先感谢。