Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么列表初始化会导致Seg故障?_C++ - Fatal编程技术网

C++ 为什么列表初始化会导致Seg故障?

C++ 为什么列表初始化会导致Seg故障?,c++,C++,我正在调试应用程序的未定义行为。今天,我有机会尝试了-fsanitize=undefined-fsanitize=address标志,像往常一样,我继续编译我的应用程序。结果是,它在运行时发现了一些东西并打印出了这个日志 AddressSanitizer:DEADLYSIGNAL ================================================================= ==502288==ERROR: AddressSanitizer: SEGV on

我正在调试应用程序的未定义行为。今天,我有机会尝试了
-fsanitize=undefined-fsanitize=address
标志,像往常一样,我继续编译我的应用程序。结果是,它在运行时发现了一些东西并打印出了这个日志

AddressSanitizer:DEADLYSIGNAL
=================================================================
==502288==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x0000004ce04b bp 0x611000000b98 sp 0x7ffc441a5bf8 T0)
==502288==The signal is caused by a READ memory access.
==502288==Hint: this fault was caused by a dereference of a high value address (see register values below).  Dissassemble the provided pc to learn which register was used.
    #0 0x4ce04b in llhttp__on_message_begin /home/llhttp/src/native/api.c:144:3
    #1 0x4ce4f4 in llhttp__internal__run /home/llhttp/build/c/llhttp.c:14590:13
    #2 0x4ce3e1 in llhttp__internal_execute /home/llhttp/build/c/llhttp.c:14624:10
    #3 0x4c8661 in HTTPTransport::initialize() /home/example.cpp:70:29
    #4 0x4c890f in main /home/example.cpp:76:12
    #5 0x7f09e9f590b2 in __libc_start_main /build/glibc-ZN95T4/glibc-2.31/csu/../csu/libc-start.c:308:16
    #6 0x41d53d in _start (/home/example+0x41d53d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/llhttp/src/native/api.c:144:3 in llhttp__on_message_begin
==502288==ABORTING
我终于找到了原因。在这里

class Connection : public HTTPTransport
{
public:
    llhttp_t httpParser;
    llhttp_settings_t httpParserSettings;
    sessions session;

    bool auth;
     
    // This line causing it but if I remove it everything works.
    Connection() : auth(){}
};
但我发现,如果删除unique_ptr并直接初始化该类,则该行没有任何效果,从而导致segfault

有趣的是,如果我使用unique_ptr并删除该行,然后一切正常,这就不会发生

我还尝试在类中使用类内成员初始值设定方法;但它就是不工作,并抛出相同的seg故障

我是在Clang编译器上编译的,目标是C++17

总而言之,以下是我尝试过的东西,但没有以任何方式影响seg故障

  • 类内成员初始化
  • 直接初始化类,而不是
    unique\u ptr
  • 已删除该类对
    HTTPTransport
    基类的继承
我知道,
std::make_unique
不会调用类列表初始值设定项,但事实上,我在直接初始化类时遇到了相同的seg错误,我是这样初始化的

Connection currentConnection; 
最小可复制代码

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include "llhttp.h"

class HTTPTransport
{
public:
    struct sessions
    {
        std::string url;
    };

private:
    static int handleOnUrl(llhttp_t *ll, const char *buf, size_t len);

public:
    void initialize();    
};

class Connection : public HTTPTransport
{
public:
    llhttp_t httpParser;
    llhttp_settings_t httpParserSettings;
    sessions session;

    bool auth;

    Connection() : auth(){}
};
    
int HTTPTransport::handleOnUrl(llhttp_t *ll, const char *buf, size_t len)
{
    sessions *session = static_cast<sessions *>(ll->data);
    session->url = std::string(buf, len);
    return 0;
}

void HTTPTransport::initialize()
{
    auto currentConnection = std::make_unique<Connection>();

    llhttp_init(&currentConnection->httpParser, HTTP_REQUEST, &currentConnection->httpParserSettings);

    /* Set callbacks */

    currentConnection->httpParserSettings.on_url = handleOnUrl;
    currentConnection->httpParser.data = &currentConnection->session;

    std::string res = "CONNECT [2607:f8b0:4008:80c::2004]:443 HTTP/1.1\r\nHost: [2607:f8b0:4008:80c::2004]:443\r\n\r\n";

    enum llhttp_errno err = llhttp_execute(&currentConnection->httpParser, res.c_str(), res.length());
}

int main() {
    HTTPTransport Server;

    Server.initialize();

    return 0;
}
#包括
#包括
#包括
#包括
#包括“llhttp.h”
HTTPTransport类
{
公众:
结构会话
{
std::字符串url;
};
私人:
静态int handleOnUrl(llhttp\u t*ll,const char*buf,size\u t len);
公众:
void初始化();
};
类连接:公共HTTPTransport
{
公众:
llhttp_t httpParser;
llhttp_设置_t httpParserSettings;
会议;
bool-auth;
连接():auth(){}
};
int-HTTPTransport::handleOnUrl(llhttp\u t*ll,const char*buf,size\u t len)
{
sessions*session=static_cast(ll->data);
session->url=std::string(buf,len);
返回0;
}
void HTTPTransport::initialize()
{
自动currentConnection=std::使_唯一();
llhttp_init(¤tConnection->httpParser,HTTP_请求,¤tConnection->httpParserSettings);
/*设置回调*/
currentConnection->httpParserSettings.on_url=handleOnUrl;
currentConnection->httpParser.data=¤tConnection->session;
std::string res=“CONNECT[2607:f8b0:4008:80c::2004]:443 HTTP/1.1\r\n主机:[2607:f8b0:4008:80c::2004]:443\r\n\r\n”;
enum llhttp_errno err=llhttp_execute(¤tConnection->httpParser,res.c_str(),res.length());
}
int main(){
http传输服务器;
初始化();
返回0;
}
您将需要
llhttp
parser库来构建它。你可以在

值得补充的是,即使我没有使用唯一的\u ptr,行为仍然是一样的

// This line causing it but if I remove it everything works.
查看此页:

由于您需要
连接
对象可移动(通过std::unique_ptr),但不可复制,因此我建议您执行以下操作:

{
public:
    llhttp_t httpParser;
    llhttp_settings_t httpParserSettings;
    sessions session;

    bool auth;

    Connection() : auth(){}
    ~Connection() = default;

    // Non-copyable
    Connection(const Connection&) = delete;
    Connection& operator=(const Connection&) = delete;

    // Movable
    Connection(Connection&&) = default;
    Connection& operator=(Connection&&) = default;
};

编辑:您似乎只定义了默认的ctor,所以我不确定这是否是问题所在…

在默认构造函数中,您没有初始化
httpParserSettings
,这意味着在构造
连接时它将有垃圾数据,最后,
llhttp_init
将尝试使用垃圾数据。要解决此问题,请初始化默认构造函数中的所有成员:

class Connection : public HTTPTransport
{
public:
    llhttp_t httpParser;
    llhttp_settings_t httpParserSettings;
    sessions session;

    bool auth;

    Connection()
        : httpParser{},
          httpParserSettings{},
          session{},
          auth{}
    {}
};
或提供成员初始值设定人:

class Connection : public HTTPTransport
{
public:
    llhttp_t httpParser{};
    llhttp_settings_t httpParserSettings{};
    sessions session{};

    bool auth{};
    // no constructor needed in this case
};

它与没有默认构造函数的
连接一起工作的原因是
std::make_unique()
value在没有用户提供的默认构造函数的情况下初始化分配的对象。

可能相关:没有声明构造函数,你的
类连接可能是一个。谁删除了关于res生命终结的答案?答案作者删除了它。这可能不是问题,因为我怀疑llhttp存储传递的原始
const char*
指针而不是复制其内容。
std::make_unique()
将值初始化
连接
对象。如果没有用户提供的默认ctor,这意味着零初始化(后面是默认初始化)。但是有了1,就没有零初始。不确定这是否会对您的情况产生影响…@jeffbRTC这不太可能是编译器错误。为什么我必须显式定义~Connection()?您的解决方案不起作用。它输出相同的seg故障!假设所有其他成员变量也是如此(至少如果它们是基本变量或聚合变量)。基本上,我们不应该编写任何成员都可能未初始化的类。如果是基本类型或聚合类型,请在成员声明末尾粘贴一个
{}
,以避免出现这种情况。依我拙见(甚至可能养成为所有成员编写的习惯!)@IlCapitano它是有效的。我必须把{]放在std::string,std::vector的末尾吗(我在这个类的RealApp中有这些)?@underline_d我选择了
httpParserSettings
,因为
llhttp_init
似乎是用来初始化
httpParser
,所以不必严格地对其进行值初始化。不过,总的来说,我同意你的看法,应该总是初始化成员。@jeffbRTC你不必这样做,因为默认构造函数将运行regardless,但最好将
{}
放在所有成员的末尾。@jeffbRTC您不必这样做,因为“real”(经过良好编程、非聚合等)类永远不会未初始化,即使没有
{}
,也会调用默认的构造函数,但这可能是一个好习惯——因为这意味着您正在编写
{}
更多,因此以后对于基本/聚合类型不太可能忘记它。此外,这意味着您不会受您使用的类的任何人的摆布,他们自己可能有一天会忘记初始化这样的成员并给出您的代码!