【发布时间】:2021-05-18 03:03:36
【问题描述】:
我想设计一个模板函数,它建立一个size = sizeof(T) * n的共享内存
它返回模板类型指针。我将默认值作为默认值传递。
函数定义如下:
#ifndef SHMHELP_HPP_
#define SHMHELP_HPP_
#include <bits/stdc++.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
namespace cppbox {
namespace shm {
enum EmShmOpenMode:int {
MODE_CREATE,
MODE_RD,
};
template<typename T> //, T v>
T* func(const char* filename, size_t n, int rdflag, T v) { // mode: 0666
int offlag = rdflag == EmShmOpenMode::MODE_CREATE ? O_CREAT | O_EXCL | O_RDWR : offlag = O_RDWR;
int shm_fd = shm_open(filename, offlag, 0666);
if (-1 == shm_fd) {
if (rdflag != EmShmOpenMode::MODE_CREATE) {
std::cerr << "shm_open open failed: " << strerror(errno) << std::endl;
return nullptr;
}
offlag = O_RDWR| O_TRUNC;
if (-1 == (shm_fd = shm_open(filename, offlag, 0666))) {
std::cerr << "shm_open create failed: " << strerror(errno) << std::endl;
return nullptr;
}
}
if (rdflag == EmShmOpenMode::MODE_CREATE) {
if (ftruncate(shm_fd, n*sizeof(T))) {
std::cerr << "ftruncate failed: " << strerror(errno) << std::endl;
close(shm_fd);
return nullptr;
}
}
T* ret = (T*)mmap(0, n*sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
close(shm_fd);
if (ret == MAP_FAILED) {
std::cerr << "mmap failed: " << strerror(errno) << std::endl;
return nullptr;
}
if (rdflag == EmShmOpenMode::MODE_CREATE) std::fill((T*)ret, ((T*)ret) + n, v);
return ret;
}
}
};
#endif // SHMHELP_HPP_
当我打电话给func<int>("a", 100, 0, 0) 或func<double>("a", 100, 0, 0.) 时没关系
但是当我打电话给func<std::string>("a", 100, 0, "")时它崩溃了
int main() {
std::string*p = cppbox::shm::MapShm<std::string>("b", 100, cppbox::shm::MODE_CREATE, "huang");
for (int i = 0; i < 100; ++i) {
cout << (*p)[i] << " ";
}
}
当我像这样调用func<char[32]>("a", 100, 0, "") 时,编译器将拒绝编译:
int main() {
char[32]*p = cppbox::shm::MapShm<char[32]>("b", 100, cppbox::shm::MODE_CREATE, "huang"); // compiler will reject in this line
for (int i = 0; i < 100; ++i) {
cout << (*p)[i] << " ";
}//*/
}
我怎样才能使func<char[32]>("a",100, 0, "") 和func<std::string>("a", 100, 0, "") 工作?
【问题讨论】:
-
请比“它似乎不起作用”更具体。
-
这对于几分钟前被删除的另一个问题看起来非常熟悉,通过水晶球的普遍共识是您正在尝试分配数组。是的,看起来你是(来自
std::fill)。你不能。您可以做的是创建一个简单的包装器,如struct cstring32 { char s[32]; };并使用它。 -
在共享内存中存储像
std::string这样的非平凡类型将不可避免地导致未定义的行为。 -
这段代码有问题
T* ret = (T*)mmap(0, n*sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);,因为您正在为字符串分配空间,但未能构造字符串(此处未调用字符串构造函数)。如果您真的想这样做,您需要研究一种称为 placement new 的技术。该技术将允许您在分配的内存中构造对象。 -
或者,您可以使用
std::uninitialized_fill而不是std::fill。请记住,您在这里处理的是原始内存,std::fill不正确。