为什么此 C++ 成员函数调用会因分段错误而失败?
Why does this C++ member function call fail with a segmentation fault?
我关注这个论坛很多年了,发现它非常有帮助,到目前为止回答了我所有的问题。但是今天我好像卡住了。
作为 C++ 的新手,我尝试编写一些 classes 来帮助我通过代理服务器连接到网站。因此,我调用了一个 class 的函数,它封装了一些逻辑来处理 HTTP 请求。我通过引用将一个结构和另外两个参数传递给该函数。执行失败并出现分段错误 (duh)。调试显示当我调用我的函数时发生了分段错误。
在我的主函数中,我创建了一个 class 的实例,它在 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++ 的新手,所以我可能会在使用 classes 或函数或头文件的方式上犯一些非常明显的错误,但我自己似乎无法找到答案。
非常感谢您的帮助,谢谢!
编辑:
当然只有我作为一个C++菜鸟是对的,有经验的社区肯定是错误的。
所以我为了证明我的无限智慧所做的是注释掉 openHttpSocket 的内容,除了 printf()... 但突然它起作用了。所以我开始重新部分地重新包含部分代码,直到我偶然发现了这一行:
int HttpLayer::openHttpSocket(std::string address,int port,proxy_data &proxy){
...
unsigned char proxyanswer[HTTP_BUF_SIZE];
...
}
好吧,所有功劳都归功于@WhozCraig 的 crystal 舞会。以及所有其他要求我 post 函数内容的人。谢谢!
现在另一个初学者的问题:我的堆栈在这里发生了什么?以及如何创建某种可以在 C++ 的成员函数中使用的 char* 缓冲区?或者在 C++ 中是否有一个完全不同的概念可以用来代替那些好的旧字符数组?
HTTP_BUF_SIZE
是650万。这意味着这个函数范围变量声明:
unsigned char proxyanswer[HTTP_BUF_SIZE];
尝试在堆栈上创建一个大约 6MB 的缓冲区。这将在大多数默认设置下溢出堆栈。
你不想在堆栈上有这么大的对象,你想让它们在堆上。在 C++ 术语中,您不希望它们在函数中具有自动存储持续时间,您希望它们动态分配。 C++创建动态数组的方式是:
std::vector<unsigned char> proxyanswer(HTTP_BUF_SIZE);
这会动态分配内存 ("on the heap"),几乎可以用作普通数组(支持 []
下标等)。如果您需要 作为指针访问实际缓冲区(例如将其传递给 C API),您可以使用 proxyanswer.data()
(C++11 及更高版本),或 &proxyanswer.front()
(C++03 及以下版本)。
我关注这个论坛很多年了,发现它非常有帮助,到目前为止回答了我所有的问题。但是今天我好像卡住了。
作为 C++ 的新手,我尝试编写一些 classes 来帮助我通过代理服务器连接到网站。因此,我调用了一个 class 的函数,它封装了一些逻辑来处理 HTTP 请求。我通过引用将一个结构和另外两个参数传递给该函数。执行失败并出现分段错误 (duh)。调试显示当我调用我的函数时发生了分段错误。
在我的主函数中,我创建了一个 class 的实例,它在 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++ 的新手,所以我可能会在使用 classes 或函数或头文件的方式上犯一些非常明显的错误,但我自己似乎无法找到答案。
非常感谢您的帮助,谢谢!
编辑:
当然只有我作为一个C++菜鸟是对的,有经验的社区肯定是错误的。 所以我为了证明我的无限智慧所做的是注释掉 openHttpSocket 的内容,除了 printf()... 但突然它起作用了。所以我开始重新部分地重新包含部分代码,直到我偶然发现了这一行:
int HttpLayer::openHttpSocket(std::string address,int port,proxy_data &proxy){
...
unsigned char proxyanswer[HTTP_BUF_SIZE];
...
}
好吧,所有功劳都归功于@WhozCraig 的 crystal 舞会。以及所有其他要求我 post 函数内容的人。谢谢!
现在另一个初学者的问题:我的堆栈在这里发生了什么?以及如何创建某种可以在 C++ 的成员函数中使用的 char* 缓冲区?或者在 C++ 中是否有一个完全不同的概念可以用来代替那些好的旧字符数组?
HTTP_BUF_SIZE
是650万。这意味着这个函数范围变量声明:
unsigned char proxyanswer[HTTP_BUF_SIZE];
尝试在堆栈上创建一个大约 6MB 的缓冲区。这将在大多数默认设置下溢出堆栈。
你不想在堆栈上有这么大的对象,你想让它们在堆上。在 C++ 术语中,您不希望它们在函数中具有自动存储持续时间,您希望它们动态分配。 C++创建动态数组的方式是:
std::vector<unsigned char> proxyanswer(HTTP_BUF_SIZE);
这会动态分配内存 ("on the heap"),几乎可以用作普通数组(支持 []
下标等)。如果您需要 作为指针访问实际缓冲区(例如将其传递给 C API),您可以使用 proxyanswer.data()
(C++11 及更高版本),或 &proxyanswer.front()
(C++03 及以下版本)。