取消引用指向向量的空指针时出现 C++ 分段错误
C++ Segmentation fault while dereferencing a void pointer to a vector
#include <iostream>
#include <vector>
#include <mutex>
struct STRU_Msg
{
std::string name;
void *vpData;
};
class CMSG
{
public:
template <typename T>
int miRegister(std::string name)
{
STRU_Msg msg;
msg.name = name;
msg.vpData = malloc(sizeof(T));
msgtable.push_back(msg);
std::cout << "registeratio ok\n";
return 0;
}
template <typename T>
int miPublish(std::string name, T tData)
{
for (int i = 0; i < msgtable.size(); i++)
{
if (!name.compare(msgtable[i].name))
{
(*(T *)msgtable[i].vpData) = tData;
std::cout << "SUccess!\n";
return 0;
}
else
{
std::cout << "cannot find\n";
return 0;
}
}
}
private:
std::vector<STRU_Msg> msgtable;
};
int main()
{
CMSG message;
std::string fancyname = "xxx";
std::vector<float> v;
// message.miRegister< std::vector<float> >(fancyname);
// for (int i = 0; i < 1000; i++)
// {
// v.push_back(i);
// }
// std::cout << "v[0]: " << v[0] << ", v[-1]: " << v[v.size()-1] << '\n';
// message.miPublish< std::vector<float> >(fancyname, v);
for (int i = 0; i < 1000; i++)
{
v.push_back(i);
}
std::cout << "v[0]: " << v[0] << ", v[-1]: " << v[v.size()-1] << '\n';
message.miRegister< std::vector<float> >(fancyname);
message.miPublish< std::vector<float> >(fancyname, v);
return 0;
}
我想要实现的是编写一个简单的publish/subscribe(如ROS)系统,我使用void 指针以便它适用于所有数据类型。这是简化后的代码。
如果我发布一个 int,它工作正常,但真正让我困惑的是:
- 如果我传递一个长向量(像这段代码),它给了我
“分段错误(核心转储)”错误。
- 如果我在 "register" 和 "publish" 之间定义向量(即像
注释部分),此错误消失。
- 如果我使用更短的向量,比如大小为 10,无论我在哪里定义
吧,我的代码运行很顺利
我在 Linux 中使用 g++。
请帮助我修复我的代码并解释为什么会发生上述行为,在此先感谢!
您不能复制 std::vector
或任何其他类似的重要类型。在对此类对象执行任何操作(甚至赋值)之前,您需要使用 constructor 和 placement construct 它新.
一种方法是
new(msgtable[i].vpData) T;
在 register
函数中执行此操作。
然后你就可以像你一样赋值了。
更好的是,根本不要使用 malloc
,使用(正常,非放置)new
分配对象。
然而,我强烈建议放弃 void*
并转向基于模板的 STRU_Msg
实现。如果您不想重新发明轮子,只需使用 std::any
.
#include <iostream>
#include <vector>
#include <mutex>
struct STRU_Msg
{
std::string name;
void *vpData;
};
class CMSG
{
public:
template <typename T>
int miRegister(std::string name)
{
STRU_Msg msg;
msg.name = name;
msg.vpData = malloc(sizeof(T));
msgtable.push_back(msg);
std::cout << "registeratio ok\n";
return 0;
}
template <typename T>
int miPublish(std::string name, T tData)
{
for (int i = 0; i < msgtable.size(); i++)
{
if (!name.compare(msgtable[i].name))
{
(*(T *)msgtable[i].vpData) = tData;
std::cout << "SUccess!\n";
return 0;
}
else
{
std::cout << "cannot find\n";
return 0;
}
}
}
private:
std::vector<STRU_Msg> msgtable;
};
int main()
{
CMSG message;
std::string fancyname = "xxx";
std::vector<float> v;
// message.miRegister< std::vector<float> >(fancyname);
// for (int i = 0; i < 1000; i++)
// {
// v.push_back(i);
// }
// std::cout << "v[0]: " << v[0] << ", v[-1]: " << v[v.size()-1] << '\n';
// message.miPublish< std::vector<float> >(fancyname, v);
for (int i = 0; i < 1000; i++)
{
v.push_back(i);
}
std::cout << "v[0]: " << v[0] << ", v[-1]: " << v[v.size()-1] << '\n';
message.miRegister< std::vector<float> >(fancyname);
message.miPublish< std::vector<float> >(fancyname, v);
return 0;
}
我想要实现的是编写一个简单的publish/subscribe(如ROS)系统,我使用void 指针以便它适用于所有数据类型。这是简化后的代码。
如果我发布一个 int,它工作正常,但真正让我困惑的是:
- 如果我传递一个长向量(像这段代码),它给了我 “分段错误(核心转储)”错误。
- 如果我在 "register" 和 "publish" 之间定义向量(即像 注释部分),此错误消失。
- 如果我使用更短的向量,比如大小为 10,无论我在哪里定义 吧,我的代码运行很顺利
我在 Linux 中使用 g++。
请帮助我修复我的代码并解释为什么会发生上述行为,在此先感谢!
您不能复制 std::vector
或任何其他类似的重要类型。在对此类对象执行任何操作(甚至赋值)之前,您需要使用 constructor 和 placement construct 它新.
一种方法是
new(msgtable[i].vpData) T;
在 register
函数中执行此操作。
然后你就可以像你一样赋值了。
更好的是,根本不要使用 malloc
,使用(正常,非放置)new
分配对象。
然而,我强烈建议放弃 void*
并转向基于模板的 STRU_Msg
实现。如果您不想重新发明轮子,只需使用 std::any
.