0

I am so frustrated by pset6, so much unfamiliar stuff here...... please help!

I have written all the 4 to-do functions, however if I go to the web server, no matter what I clicked, it shows no more than < ?.

It seems a lot goes wrong.

So I go to gdb, setting the breakpoint at main, and find out the server.c falls into the line if(connected()) and does not show anything anymore.

I am confused because by if(connected()), it has not yet touched any of the 4 functions I wrote, there shouldn't be anything wrong....supposedly?

I really need advice, thanks!

Here is load:

/**
 * Loads a file into memory dynamically allocated on heap.
 * Stores address thereof in *content and length thereof in *length.
 */
bool load(FILE* file, BYTE** content, size_t* length)
{
    // bsic settings
    int counter = 0;
    BYTE* buffer = malloc(1);

    while(fread(buffer, 1, 1, file) == 1)
    {
        counter = counter + 1;
    }

    buffer = realloc(buffer, counter + 1);
    fread(buffer, 1, counter, file);
    *(buffer+counter) = '\0';

    *content = buffer;
    *length = counter + 1;

    if (content == NULL || length == NULL)
    {
        return false;
    }

    return true;

}
1

New load

  • The first advice is: do not think of content or treat content as "string" (char*) data. It will sink you. Because a byte containing 0 has special meaning (ie null terminator), the system will be fooled. Image data can (and usually does!) contain lots of 0 bytes. Consider a black pixel (review pset4 spec for a refresher).
  • Similarly, this declaration char* buffer = malloc(2); (and everything that goes with it: memset, free) is adding unnecessary complexity. Since the function reads file one BYTE at a time, and the program has given us a handy-dandy data type called BYTE, think about how the function could be simplified using a declaration like this BYTE buffer;.
  • Back to "string" thinking: this * length = strlen(* content) + 1; is a problem. Your program just went to all that trouble to read the bytes from file and build counter. You already have the exact info you need. And be mindful of the places you use counter + 1. That is also "string" thinking.

  • load must return a length that matches the file size exactly. When you are using gdb, you might want to know what length to expect. One way to find the size/length of a file is the ls -al command. If you are in your public directory, ls -al will give output similar to this, file lengths highlighted:

    enter image description here

  • Remember, when you make a request to your server, as with CS50 IDE > Web Server, the first thing it requests is the "document root", followed by favicon.ico. It might be easier to send a curl request like curl -i http://localhost:8080/hello.html when you are troubleshooting with gdb.

  • Frustration is the enemy. This pset is quite challenging, to be sure. Trust what you know, research/review what you don't, and use the tools (debug50, gdb, valgrind).


Original analysis This sizeof(BYTES) might not be the only problem, but it is significant. BYTES is an integer. sizeof an integer is 4. I don't think that's what you intended. It's used in two places in the load function.

And make sure you review the spec

given a /path/to/a/directory, returns /path/to/a/directory/index.php if index.php actually exists therein, or /path/to/a/directory/index.html if index.html

Order matters. (This is not related to the errors you are facing, but it will be a factor with check50/server2).

When you use gdb, it is usually a good idea to set breakpoints at the functions you wrote, instead of main.

6
  • I fixed the problem you pointed out, and tried gdb again. this time I set break point at parse and using curl to request hello.html. I followed the instruction here cs50.stackexchange.com/questions/16688/debugging-webserver-in-c/… However, the gdb does not show any error, the code gets HTTP/1.1 200 OK. and then goes back to if(connected()), and stuck in there again..... I need some more clue.... thanks!
    – user13479
    Oct 6 '16 at 8:24
  • I think I am a step closer. My parse function passes all the server1 check. Therefore I run it with gdb again, this time with the break point at load. It turns out load function execute "while (fread(buffer, 1, 1, file) == 1)" twice before "counter = counter + 1;". I think here is the problem. But cant see why fread is run twice. After load, gdb keeps running, in the end it reads: Program received signal SIGPIPE, Broken pipe. 0x00007ffff77fa710 in __write_nocancel () at ../sysdeps/unix/syscall-template.S:81 81 ../sysdeps/unix/syscall-template.S: No such file or directory.
    – user13479
    Oct 6 '16 at 11:01
  • Sorry I dont think I understand, still need help. I don't think I treat content as a string, rather, in my code, I treat *content as an address pointing to a string. I thought that's how address works, is it not? And why (counter + 1) is a string thinking? Counter is an int.
    – user13479
    Oct 7 '16 at 1:44
  • This * length = strlen(* content) + 1 seems to me treating content as a string, since strlen is a string function. This * content = realloc (* content, counter + 1); seems to me string thinking because of the +1 (for the null-byte?) Oct 7 '16 at 13:13
  • I changed the way using *content and I rewrite *length = counter + 1; to stop from treating content as a string. However it still does not work. And I could not figure out how to simplify by putting just BYTE buffer, since fread requires an address to write in, it can't be a char. I definitely need more advices....I updated the code.
    – user13479
    Oct 8 '16 at 0:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .