C++ 共享内存如何彻底删除?

五岳凌峰 五岳凌峰 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
进程M(比如M.exe)创建了两个线程,主线程A和子线程B。在函数ThreadA::CaptureImage中创建共享内存,往共享内存写入数据;在ThreadB::CaptureImage中打开共享内存,从共享内存读取数据;
HRESULT ThreadA::CaptureImage(para1,para2)
{
...
// memory size
int MemorySize = ImageWidth * ImageHeight;
// share memory name
_bstr_t csShareMemoryName = _T("CaptureImage");
//create share memory
HANDLE hShareMemoryHandle = NULL;
hShareMemoryHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, csShareMemoryName);
if (NULL == hShareMemoryHandle)
{
hShareMemoryHandle = ::CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
nInit,
MemorySize,
csShareMemoryName);
DWORD dwCurrentThreadID = GetCurrentThreadId();
CString test_CaptureImage;
test_CaptureImage.Format(_T("### [TID]:%d, memorysize=%d"), long(dwCurrentThreadID), MemorySize);
OutputDebugString(test_CaptureImage);
// Check if create share memory successfully
if (NULL == hShareMemoryHandle)
{
if (pImageData != NULL)
{
delete[] pImageData;
pImageData = NULL;
}
return E_FAIL;
}
}
// Map the sharing memory.
LPVOID pShareMemoryAddress = MapViewOfFile(
hShareMemoryHandle,
FILE_MAP_ALL_ACCESS,
nInit,
nInit,
nInit);
BYTE* pBuffer = reinterpret_cast<BYTE*>(pShareMemoryAddress);

// Fill the sharing memory.
memcpy(pBuffer, pImageData, MemorySize);
// Unmaps a mapped view of a file from the address space of the calling process.
UnmapViewOfFile(pShareMemoryAddress);

if (pImageData != NULL)
{
delete[] pImageData;
pImageData = NULL;
}
...
return S_OK;
}

HRESULT ThreadB::CaptureImage( para1,... )
{
...
// memory size
int MemorySize=GetMemorySize();
// share memory name
_bstr_t csShareMemoryName = _T("CaptureImage");
//open file mapping
HANDLE hShareMemoryHandle = OpenFileMapping(
FILE_MAP_ALL_ACCESS,
FALSE,
csShareMemoryName);
if (NULL == hShareMemoryHandle)
{
return E_FAIL;
}
// Map the sharing memory.
LPVOID pShareMemoryAddress = MapViewOfFile(
hShareMemoryHandle,
FILE_MAP_READ,
nZero,
nZero,
nZero);
if (NULL == pShareMemoryAddress)
{
return E_FAIL;
}

BYTE* pBuffer = new BYTE[MemorySize];
memcpy(pBuffer, pShareMemoryAddress, MemorySize);

UnmapViewOfFile(pShareMemoryAddress);
CloseHandle(hShareMemoryHandle);
...
return S_OK;
}

问题:因为共享内存名字保持不变,当多次调用ThreadA::CaptureImage时,操作系统(或者叫内核对象?)会检查该共享内存名字是否已存在,如果存在,不再创建。 就是说,ThreadA::CaptureImage第一次被调用时,共享内存"CaptureImage"才会创建,后面再被调用,不再创建。且共享内存大小是第一次指定的大小,不会改变。假设第一次指定的大小为1000,当第2次调用ThreadA::CaptureImage时,需要的共享内存大小为4000。由于共享内存没有以4000重新创建,保持1000。当程序执行到代码行
	// Fill the sharing memory.
memcpy(pBuffer, pImageData, MemorySize);

会出现指针地址越界的情况。
考虑的解决方案如下:
方案1:根据指定大小创建共享内存,例如共享内存名字格式为CaptureImage_1000,CaptureImage_4000等。该方案简单,自己已经实现。

方案2:不修改共享内存名字。ThreadB::CaptureImage中读取共享内存数据后,把共享内存彻底删除。这样,每次调用ThreadA::CaptureImage时,
OpenFileMapping返回值为NULL,然后重新创建共享内存。通过该调用什么函数彻底删除共享内存?函数FlushViewOfFile?
如果没有删除共享内存的函数,那共享内存的生存周期和进程M相同?

方案3:不修改共享内存名字,有没有扩容的函数?就是比较前后两次指定的共享内存大小,如果本次指定的比上一次指定的大,就在上一次基础上扩大共享内存大小?

倾向用方案2。方案1虽然简单,举个极端例子,假设重复调用ThreadA::CaptureImage,10000次,每次共享内存大小都不一样,这样就得创建10000个共享内存,个人认为资源利用率较低。方案3,可能没有这样的扩容函数。 想请教大家,方案2的实现思路。谢谢
...全文

相关推荐

C++实现的共享内存缓冲区

atu_shm_buffer.cpp文件中定义了一个名为atu_shm_buffer的C++类,该类通过共享内存和同名信号量实现多进程间的同步读写操作。类提供了创建、读取、写入、删除共享内存及信号量的

atu8292991

C++共享内存动态库:memoryShare的深入解析

库提供以下核心功能:创建和销毁共享内存:可以创建和销毁共享内存段,支持在多个进程间共享数据。内存映射和访问:允许进程将共享内存段映射到它们的地址空间,并进行读写操作。同步机制:通过信号量、互斥锁等同步机制,确保多个进程对共享内存的访问不会造成数据竞争。的这些功能构建于操作系统提供的基础功能之上,同时隐藏了底层系统的复杂性,为开发者提供了一个简洁的API接口。

宁柳跨越

Android调用C++实现共享内存

**安全性和清理**: 为了防止资源泄漏,当不再需要共享内存时,必须正确地删除它。在C++中,`shmdt()`函数用来解除进程对共享内存的映射,`shmctl()`函数可以用于删除共享内存。

若无ly

python和C++共享内存传输图像的示例

本文主要介绍如何使用Python与C++通过共享内存进行图像数据的传输,具体涉及了C++创建共享内存库以及Python调用该库的过程。在跨语言的编程中,尤其是涉及到性能敏感的数据传输时,共享内存

weixin_38537315

c++实现链表删除.cpp

c++实现链表删除.cpp

weixin_42818365
评论 2
收藏 已收藏
分享
返回顶部
五岳凌峰
C++ 语言 65,214 成员 250,514 内容