简体   繁体   English

只有逐步调试,代码才能正常运行

[英]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) 昨天关闭笔记本电脑后,服务器运行正常,但是今天它仅发送http标头(我没有做任何更改)
  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. 但是如果我将其更改为此,它仅发送文件的〜2%。 And that's not a random number, it actually only sends about 2% of the file. 这不是一个随机数,它实际上仅发送文件的2%。

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. 将字符串更改为char *不能解决问题。

  • I'm using visual studio2010. 我正在使用visual studio2010。 If I run my code step-by-step, I am able to solve problem #1, everything gets sent. 如果我逐步执行代码,则能够解决问题#1,一切都将发送出去。 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. 在调试时行为不同的C ++代码几乎总是未初始化(或未正确初始化)的变量。

Can you show us the declaration of data ? 您能告诉我们data声明吗? TempSocket ? 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. 假设data是某种大小的char[] ,并且该stringstd::string您的代码不会执行您认为的操作。 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. 当您将数据传递到WEB::Send它将创建一个std::stringdata所有字节一直到第一个0,大约是总数据的2%。 You want to call web.Send(std::string(data, n)); 您想调用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. 同样在WEB::Send您需要调用data.data()而不是c_str()来避免相同的null问题。

Read bytes can be not equal to actual size of your string, as you don't init data in loop every time. 读取的字节数不能等于字符串的实际大小,因为您不会每次都在循环中初始化data But in the first case you specify size of data equal n and in the second case you send of size data.size() . 但是在第一种情况下,您指定的数据大小等于n ,在第二种情况下,您发送的大小为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. 我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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