为什么这个C++成员函数调用会失败并出现分段错误

Why does this C++ member function call fail with a segmentation fault?

本文关键字:分段 错误 失败 C++ 成员 函数调用 为什么      更新时间:2023-10-16

我关注这个论坛多年,发现它非常有帮助,回答了我到目前为止的所有问题。但今天我似乎被困住了。

作为C++新手,我尝试编写一些类,以帮助我通过代理服务器连接到网站。因此,我调用了一个类的函数,该函数封装了一些逻辑来处理HTTP请求。我通过引用将一个结构和另外两个参数传递给这个函数。执行失败,并出现分段错误 (duh)。调试显示调用函数时发生分段错误。

在我的主函数中,我创建了一个在 httplayer.hpp 中声明的类的实例,并像这样调用它的成员之一:

#include "../include/httplayer.hpp"
int main(int argc,char** argv){
    HttpLayer httplayer;
    proxy_data proxy;
    proxy.username="name";
    proxy.password="pwd";
    proxy.address="some.address";
    proxy.port="8080";
    int n = httplayer.openHttpSocket("google.com",8080,proxy); //Here the catasprohy happens
    //more stuff
    return 0;
}

httplayer.hpp 文件如下所示:

#include <iostream>
#include <cstring>
#include <string>
#include "../include/commlayer.hpp"

struct proxy_data{
        std::string username, password, address, port;
};
class HttpLayer{
    public:
        static const int HTTP_BUF_SIZE = 6555648;
        int closeHttpSocket();
        int requestHttp(std::string, char*);
        int openHttpSocket(std::string, int, struct proxy_data&);
    private:
        bool endsWith(std::string const & value, std::string const & ending);
        CommLayer comm;
};

在相应的 httplayer 中.cpp我终于有了这个函数:

int HttpLayer::openHttpSocket(std::string address,int port,proxy_data &proxy){  

GDB 显示以下信息:

14 int n = httplayer.openHttpSocket("google.com",8080,proxy);
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x0804940b in HttpLayer::openHttpSocket (
    this=<error reading variable: Cannot access memory at address 0xbf37d81c>, 
address=<error reading variable: Cannot access memory at address 0xbf37d818>, port=8080, 
proxy=<error reading variable: Cannot access memory at address 0xbf37d814>)
at src/httplayer.cpp:20
20  int HttpLayer::openHttpSocket(std::string address,int port,proxy_data &proxy){

我的第一个怀疑是结构,但到目前为止还无法看到我的错误。我是C++新手,所以我可能会在使用类、函数或头文件的方式上犯一些非常明显的错误,但我似乎无法自己找到。

非常感谢

您的帮助,谢谢!

编辑:

当然,只有我作为一个C++菜鸟是对的,有经验的社区一定是错误的。所以我所做的证明我无限智慧的是注释掉 openHttpSocket 的内容,除了 printf()...但突然间它奏效了。所以我开始再次重新包含部分代码,直到我偶然发现这一行:

int HttpLayer::openHttpSocket(std::string address,int port,proxy_data &proxy){
    ...
    unsigned char proxyanswer[HTTP_BUF_SIZE];
    ...
}

好吧,所有的功劳都归功于@WhozCraig的水晶球。并致其他所有人要求我发布该功能的内容。谢谢!

现在另一个初学者的问题:我的堆栈在这里会发生什么?如何创建某种可以在 C++ 中的成员函数中使用的 char* 缓冲区?还是C++中有一个完全不同的概念来代替那些好的旧字符数组?

HTTP_BUF_SIZE是650万。这意味着这个函数范围的变量声明:

unsigned char proxyanswer[HTTP_BUF_SIZE];

尝试在堆栈上创建大约 6MB 的缓冲区。这将在大多数默认设置下溢出堆栈。

不希望对象在堆栈上这么大,你希望它们在堆上。C++而言,您不希望它们在函数中具有自动存储持续时间,而是希望它们动态分配。创建动态数组C++方法是:

std::vector<unsigned char> proxyanswer(HTTP_BUF_SIZE);

这会动态分配内存("在堆上"),并且几乎可以用作普通数组(支持[]下标等)。如果需要以指针的形式访问实际缓冲区(例如,将其传递给 C API),则可以使用 proxyanswer.data()(C++11 及更高版本)或&proxyanswer.front()(C++03 及更低版本)。