views:

274

answers:

4

I'm new to the C/C++ game so I assume I'm making a rookie mistake:

int main(){
  char* clen;
  clen = getenv("CONTENT_LENGTH");
  if (clen==NULL){
    cout << "No such ENV var: CONTENT_LENGTH"<<endl;
    exit(0);
  }
  int cl = 0; 
  cl = atoi(clen);
  if (cl < 1){
    return inputPage();
  }

  // if there is no content, we assume that this is a fresh request, 
//   so we showed the input page, otherwise, we'll return dispatch to 
  //the processing code.
  postTest(clen);

}

This is supposed to be a CGI script. As far as I can tell with GDB, print statements, etc. this code segfaults on the line "cl = atoi(clen);" I have no idea why this is. K&R suggests that this is correct. I basically copied this line from a half dozen other online tutorials. And it seemed to be working last night! I'm totally stumped.

+1  A: 

Barring compiler bugs and a bugged getenv() implementation I would say that it's impossible for that code to segfault on cl = atoi(clen). This is because getenv() returns either NULL or a valid pointer to a null terminated character array (that's just a fancy way to say C string).

Since the NULL case is checked against, most likely the program (it's not a "script") crashes somewhere else.

EDIT: How do you know it even crashes? Does it display an HTTP 500 error? If yes most likely you simply forgot cout << "Content-type: text/html\n\n". What do the web server logs say?

EDIT2: unrelated to your problem, but usually using C functions like atoi() is frowned upon; the C++ version lexical_cast (implemented in TR1 and boost) is preferred.

Andreas Bonini
Yes, 500 error. Ok, it's not a script, fair enough. thanks for the lexical_cast tip, but I have to say, in the world I program in, C++ is frowned upon... ;)
Ben
+1  A: 

I don't believe that it really crashes on atoi()

Could you please try out this code?

#include <iostream>
#include <stdlib.h>
#ifndef NULL
#define NULL 0
#endif

using namespace std;

int main(){
  char* clen;
  clen = getenv("CONTENT_LENGTH");
  if (clen==NULL){
    cout << "No such ENV var: CONTENT_LENGTH"<<endl;
    exit(0);
  }
  int cl = 0;
  cl = atoi(clen);
  if (cl < 1){
        std::cout << "return inputPage();" << std::endl;
        return 0;
  }

    std::cout << "postTest();" << std::endl;

}

compile it e.g. to "app" and run it with some variations of CONTENT_LENGTH, e.g.

./app
CONTENT_LENGTH=4 ./app
CONTENT_LENGTH=-4 ./app
CONTENT_LENGTH=a ./app
Ok, looks like that idea is the lead i needed. For those interested at home, I'm running this on a school cluster, and don't seem to have access to the apache logs that i'd need without tracking down the prof, and at this point in the semester, that's a tricky task. Thanks, though, I think things are looking up...
Ben
A: 

You write you've been looking at it with GDB. Shouldn't it be possible to just dig (step) into the atoi() function call to get a better idea of what's going on? I assume you made sure it never reaches the line past the atoi() call?

dispanser
A: 

It turns out that this was not in any way an issue with atoi, or with C++ in general. The problem was that I had forgotten a very basic CGI point, which is that there is no CONTENT_LENGTH in a GET, which is what the first call from the browser inevitably is. Thus, I was trying to fiddle with the clen which was null. I simply needed to return the inputPage as soon as I discovered that there was no CONTENT_LENGTH attribute.

Ben