0

I have followed this forum for years and found it extremely helpful, answered all of my questions so far. But today I seem to be stuck.

Being new to C++ I attempted to code some classes that help me to connect to a website through a proxy server. I therefore call a function of a class that encapsulates some logic to process HTTP requests. I pass a struct and two more parameters to this function by reference. The execution fails with a Segmentation Fault (duh). Debugging shows that the Segmentation Fault occurs when I call my function.

In my main function I create an instance of a class which is declared in httplayer.hpp and call one of it's members like this:

#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;
}

the httplayer.hpp file looks like this:

#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;
};

In the corresponding httplayer.cpp I have finally this function:

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

gdb shows the following information:

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){

My first suspect was the struct, but wasn't so far able to see my mistake. I am new to C++, so I might do some horribly obvious mistake in the way I use classes or functions or header files, but I seem to be unable to find out myself.

Your help is highly appreciated, Thank you!

EDIT:

Of course only I as a C++ noob can be right and the experienced community has to be mistaken. So what I did to prove my infinite wisdom is to comment out the content of openHttpSocket except a printf()... but suddendly it worked. So I started to re-include part by part of the code again until I stumbled accross this line:

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

Well, all credit goes to @WhozCraig 's crystal ball here. And to everyone else asking me to post the content of the function. Thank you!

Now another beginner's question: What happens to my stack here? And how do I create some kind of char* buffer that I can use in a member function in C++? Or is there a complete different concept in C++ that is to be used instead of those good old char arrays?

  • 6
    Show us the code of openHttpSocket method. – Sergei Nikulov Jan 22 '15 at 07:35
  • Push `s` instead of `n` and step into the function. Or provide a minimal example that displays the issue instead of what you think is wrong. – user657267 Jan 22 '15 at 07:35
  • 1
    [Works for me](http://ideone.com/56Pfv9), so the problem is in something you haven't shown. Please narrow your real code down to an [MCVE](http://stackoverflow.com/help/mcve) and post that. Basically, something we could copy & paste to ideone and observe the behaviour ourselves. – Angew is no longer proud of SO Jan 22 '15 at 07:37
  • if I step into openHttpSocket with s I immediately receive the same Segmentation Fault error message. I thus thought that the content of the openHttpSocket() is not relevant to the problem. To be sure I included a printf in the first line that doesn't get hit before the segfault. Is the code still relevant, @Sergey? – Christian Panhuber Jan 22 '15 at 07:43
  • There is a bunch of ints who's meaning is far from clear. If you use those as error-code, stop doing that right now, use exceptions instead. That said, it's not the function call that is wrong, it is the object used in that function call already, hence the `this=` in the error message. Still, provide an MCVE, as Angew suggested. – Ulrich Eckhardt Jan 22 '15 at 07:43
  • @ChristianPanhuber The code you are showing us is where the program finally breaks down. It isn't where the problem originated. So yes, please show the code that you may not think is relevant. Also, you don't need to specify `struct` in the parameter list. C++ knows you're passing a struct,so it doesn't need constant reminding. – PaulMcKenzie Jan 22 '15 at 07:45
  • 1
    I'm going to brush off the dust from my crystal ball and predict you have a buffer something of the form `unsigned char buff[HTTP_BUF_SIZE]` in your `openHttpSocket` member (and *boom* goes your stack). Now, show the code please. – WhozCraig Jan 22 '15 at 07:47
  • BTW, I see no constructor of HttpLayer, so it is possible that you using uninitialized variables. – Sergei Nikulov Jan 22 '15 at 07:51
  • @Sergey if `CommLayer` has a proper constructor, `HttpLayer` doesn't need one. The default provision will work. *That* class` constructor (`CommLayer`) would appear to be a wild-card worthy of inspection, however, assuming what we see in `HttpLayer`'s decl here is in-fact all there is. – WhozCraig Jan 22 '15 at 07:54
  • We need the code of openHttpSocket to help you – LPs Jan 22 '15 at 08:22
  • @WhozCraig well yes that was it, thanks! Would you mind explaining me what happened to my stack? `HttpLayer` 's declaration is in fact complete – Christian Panhuber Jan 22 '15 at 08:28
  • @ChristianPanhuber [This will save me some typing](http://stackoverflow.com/questions/7902228/segmentation-fault-large-arrays). There are many other's like it on SO, but the idea is the same. You generally have a limited amount of automatic variable space with nearly all implementations. – WhozCraig Jan 22 '15 at 08:36

1 Answers1

1

HTTP_BUF_SIZE is 6.5 million. Which means that this function-scope variable declaration:

unsigned char proxyanswer[HTTP_BUF_SIZE];

tries to create a buffer of about 6MB on the stack. This will overflow the stack under most default settings.

You don't want object this big on the stack, you want them on the heap. In C++ terms, you don't want these with automatic storage duration in the function, you want them dynamically allocated. The C++ way to create a dynamic array is:

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

This allocates the memory dynamically ("on the heap") and can be used pretty much as a normal array (supports [] subscripting etc.). If you need access to the actual buffer as a pointer (to pass it to C APIs, for example), you can use proxyanswer.data() (C++11 and beyond), or &proxyanswer.front() (C++03 and below).

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • 1
    @ChristianPanhuber Worth noting: `std::vector<>` will value-initialize the elements in a pre-size like this. I.e. it will put `unsigned char()` in each element (and thus fill it with zeros, one at a time). That can have a *significant* performance impedance. If you don't care about the buffer value initialization (i.e. you're going to be filling it yourself soon anyway), consider [`std::unique_ptr`](http://en.cppreference.com/w/cpp/memory/unique_ptr) to manage a raw, uninitialized buffer instead. – WhozCraig Jan 22 '15 at 08:45