简体   繁体   中英

Code only runs properly if debugging step-by-step


I'm making a webserver and I've come up with some very strange problems.

  1. My server was running as expected yesterday when I turned off my laptop, but today it only sends the http headers (I didn't change anything)
  2. When a user requests a file, if I send them using the following code, it works perfectly:

while ((n = fread(data, 1, sizeof(data), file)) > 0) send(ts, data, n, 0);

but if I change it to this, it only sends ~2% of the file. And that's not a random number, it actually only sends about 2% of the file.

while ((n = fread(data, 1, sizeof(data), file)) > 0)
web.Send(data);

int WEB::Send(string data)
{
    return send(TempSocket, data.c_str(), data.size(), 0);
}

changing string to char* doesn't solve the problem.

  • I'm using visual studio2010. If I run my code step-by-step, I am able to solve problem #1, everything gets sent. And that is my main problem. I do not understand why it happens. Hopefully someone can explain it to me.

Thanks in advance.

EDIT:

int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmd,int nShow)
{
    SOCKET MainSocket=0;
    MSG msg;


    RedirectIOToConsole();





    CreateThread(NULL, NULL, ListenThread, NULL, NULL, NULL);



    while (GetMessage(&msg, NULL, 0, 0)) 
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }


    WSACleanup();
    closesocket(MainSocket);
    MainSocket = INVALID_SOCKET;

    return msg.wParam;
}

DWORD WINAPI ListenThread(LPVOID lparam)
{
    SOCKET MainSocket;
    WSADATA wsaData;
    SOCKET tmpsock;
    struct sockaddr_in local, from;
    int fromlen=sizeof(from);

    WSAStartup(MAKEWORD(2, 2), &wsaData);


    local.sin_family=AF_INET;
    local.sin_addr.s_addr=INADDR_ANY;
    local.sin_port=htons(PORT);
    MainSocket=socket(AF_INET,SOCK_STREAM,0);

    if(MainSocket==INVALID_SOCKET)
    {
        return 0;
    }
    if(bind(MainSocket,(struct sockaddr*)&local,sizeof(local))!=0)
    {
        return 0;
    }
    if(listen(MainSocket,10)!=0)
    {
        return 0;
    }


    while(1)
    {
        tmpsock = accept(MainSocket,(struct sockaddr*)&from,&fromlen);
        CreateThread(NULL, NULL, SlaveThread, (LPVOID)tmpsock, NULL, NULL);
    }

}

DWORD WINAPI SlaveThread(LPVOID lparam)
{
    SOCKET ts = (SOCKET)lparam;//temporary socket
......

char data[4096];
                    int n;
                    unsigned long int length = statbuf.st_size;

                    web.SendHeaders(200, "OK", format("Content-Disposition: attachment; filename=\"%s\"", FileName.c_str()).c_str(), web.GetMimeType(ReqPath.c_str()), length, statbuf.st_mtime);
                    unsigned long int i=0,d=0;
                    while ((n = fread(data, 1, sizeof(data), file)) > 0)
                    {
                        d+=send(ts, data, n, 0);
                        i+=n;
                    }
                    printf("%i=%i=%i\n", length,i,d);
                    fclose(file);

C++ code which behaves differently when debugging is almost always an uninitialized (or incorrectly initialized) variable.

Can you show us the declaration of data ? TempSocket ?

You'll have to show us more code to tell you more.

Assuming that data is char[] of some size, and that string is std::string your code doesn't do what you think it does. When you pass data to WEB::Send it's creating a std::string from all the bytes in data up to the first 0, which probably is about 2% of the total data. You want to call web.Send(std::string(data, n)); instead.

Also in WEB::Send you need to call data.data() instead of c_str() to avoid the same problems with nulls.

Read bytes can be not equal to actual size of your string, as you don't init data in loop every time. But in the first case you specify size of data equal n and in the second case you send of size data.size() . There might be trash in the end.

As it could be seen from your source code, you're using threads. I suppose that you have to synchronize them in a proper way. Why? As you said, your program works correct if it is executed step by step in debug mode; otherwise it doesn't. The only difference between these kinds of execution (step by step or the whole program at once) are timings. Step by step is slower, and there is obviously enough time for some of your threads to finish some job. On some machines your program might work correct even if you don't change anything. It's randomness. So - you have to pay attention how do you synchronize threads.

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM