简体   繁体   English

取消引用指向向量的空指针时出现 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;
}

What I want to achieve is to write a simple publish/subscribe (like ROS) system, I use void pointer so that it works for all data type.我想要实现的是编写一个简单的发布/订阅(如 ROS)系统,我使用 void 指针,以便它适用于所有数据类型。 This is the simplified code.这是简化的代码。

If I publish an int, it works fine, but what really confuse me are:如果我发布一个 int,它工作正常,但真正让我感到困惑的是:

  1. If I pass a long vector (like this code), it gave me the " segmentation fault (core dump) " error.如果我传递一个长向量(如这段代码),它会给我“分段错误(核心转储) ”错误。
  2. If I define the vector between "register" and "publish" (ie like the commented part), this error goes away.如果我在“注册”和“发布”之间定义向量(即像注释部分一样),这个错误就会消失。
  3. If I use a shorter vector, like size of 10, no matter where I define it, my code run smoothly.如果我使用较短的向量,例如大小为 10,无论我在哪里定义它,我的代码都可以顺利运行。

I use g++ in Linux.我在 Linux 中使用 g++。

Please help me fix my code and explain why above behaviors will happen, thanks in ahead!请帮我修复我的代码并解释为什么会发生上述行为,谢谢!

You cannot copy std::vector or any other non-trivial type like that.您不能复制std::vector或任何其他类似的非平凡类型。 Before you do anything (even assignment-to) with such an object, you need to construct it using a constructor and placement new .在对这样的对象执行任何操作(甚至赋值)之前,您需要使用构造函数放置 new构造它。

A way to do this would be一种方法是

new(msgtable[i].vpData) T;

Do this in the register function.register函数中执行此操作。

Then you can assign a value as you do.然后你可以像你一样分配一个值。

Still better, do not use malloc at all, allocate your object with (normal, non-placement) new .更好的是,根本不要使用malloc ,使用(正常,非放置) new分配您的对象。

I however strongly suggest ditching void* and moving to a template based implementation of STRU_Msg .然而,我强烈建议放弃void*并转向基于模板的STRU_Msg实现。 If you don't feel like reinventing the wheel, just use std::any .如果您不想重新发明轮子,只需使用std::any

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM