为什么此C ++成员函数调用因分段错误而失败?

时间:2015-01-22 07:29:38

标签: c++ linux function struct segmentation-fault

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

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

在我的main函数中,我创建了一个在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 ++中是否有一个完全不同的概念来代替那些好的旧char数组?

1 个答案:

答案 0 :(得分:1)

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及更高版本)或{{ 1}}(C ++ 03及以下)。