Valgrind -未初始化的值和字节

Valgrind - uninitialized values and bytes?

本文关键字:字节 初始化 Valgrind      更新时间:2023-10-16

Valgrind给我的错误是-

Syscall param write(buf) points to uninitialised byte(s)

Conditional jump or move depends on uninitialised value(s)

我不知道如何解决这个问题。所有的错误都在同一个地方。我有一个tcp服务器与其客户端通信的函数。如果它从任何客户机接收到消息,它将该消息传递给另一个函数。所有的错误都发生在我调用这个函数的时候。不幸的是,Valgrind没有给我函数的行号,它只是说

by 0x805683F: TcpServer::getSendBack(char*, char) (basic_string.h:2503).

其中一个的整个错误信息是-

==8759== 1 errors in context 1 of 5:
==8759== Syscall param write(buf) points to uninitialised byte(s)
==8759==    at 0x446CFDB: ??? (syscall-template.S:82)
==8759==    by 0x4416B3E: new_do_write (fileops.c:530)
==8759==    by 0x4416E55: _IO_do_write@@GLIBC_2.1 (fileops.c:503)
==8759==    by 0x441793C: _IO_file_overflow@@GLIBC_2.1 (fileops.c:881)
==8759==    by 0x4416C87: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1358)
==8759==    by 0x440CA9D: fwrite (iofwrite.c:45)
==8759==    by 0x4300DE5: __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char>     >::xsputn(char const*, int) (in /usr/lib/libstdc++.so.6.0.13)
==8759==    by 0x4303691: std::basic_ostream<char, std::char_traits<char> >&     std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char,     std::char_traits<char> >&, char const*, int) (in /usr/lib/libstdc++.so.6.0.13)
==8759==    by 0x8056825: TcpServer::getSendBack(char*, char) (ostream:510)
==8759==    by 0x805729C: TcpServer::communicate() (tcpserver.cpp:369)
==8759==    by 0x805B7B1: ServerControl::control() (servercontrol.cpp:173)
==8759==    by 0x804FE6E: main (main.cpp:230)
==8759==  Address 0x4028110 is not stack'd, malloc'd or (recently) free'd
==8759==  Uninitialised value was created by a stack allocation
==8759==    at 0x8056FA6: TcpServer::communicate() (tcpserver.cpp:304)

和另一个错误-

==8759== 1 errors in context 2 of 5:
==8759== Conditional jump or move depends on uninitialised value(s)
==8759==    at 0x4416D8C: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1317)
==8759==    by 0x440CA9D: fwrite (iofwrite.c:45)
==8759==    by 0x4300DE5: __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char> >::xsputn(char const*, int) (in /usr/lib/libstdc++.so.6.0.13)
==8759==    by 0x4303691: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int) (in /usr/lib/libstdc++.so.6.0.13)
==8759==    by 0x805683F: TcpServer::getSendBack(char*, char) (basic_string.h:2503)
==8759==    by 0x805729C: TcpServer::communicate() (tcpserver.cpp:369)
==8759==    by 0x805B7B1: ServerControl::control() (servercontrol.cpp:173)
==8759==    by 0x804FE6E: main (main.cpp:230)
==8759==  Uninitialised value was created by a stack allocation
==8759==    at 0x8056FA6: TcpServer::communicate() (tcpserver.cpp:304)

main 230只是一个对servercontrol中的控制函数的调用,而servercontrol 173只是一个pthread_create调用。

如果有人能帮我找出为什么我得到这些错误,我将非常感激。通讯功能为-

void TcpServer::communicate() {

fd_set read_flags, write_flags; // the flag sets to be used
int sel;        // holds return value for select();
int numRead = 0;    //holds return value for read()
int numSent = 0;    //holds return value for send()
char in[255];   //in buffer for client 1
char out[512];  //out buffer
//clear buffers
memset(&in, 0, 255);
memset(&out, 0, 512);
int nfds = 0;
for(int i=0;i<count;i++)
    nfds += clients[i].fd;
while(!done) {
    //reset the fd_sets
    FD_ZERO(&read_flags);
    FD_ZERO(&write_flags);
    FD_SET(STDIN_FILENO, &read_flags);
    FD_SET(STDIN_FILENO, &write_flags);
    //put fds back in
    for(int i=0;i<count;i++) {
        FD_SET(clients[i].fd, &read_flags);
        FD_SET(clients[i].fd, &write_flags);
    }   //end for
    //call select
    sel = select(nfds+1, &read_flags, &write_flags, (fd_set*)0, 0);
    //if an error with select
    if(sel < 0)
        continue;
    //loop through clients
    for(int i=0;i<count;i++) {
        //check if ready for reading
        if(FD_ISSET(clients[i].fd, &read_flags)) {
            //clear set
            FD_CLR(clients[i].fd, &read_flags);
            //clear in
            memset(&in, 0, 255);
            numRead = recv(clients[i].fd, in, 255, 0);
            if(numRead < 0) {
                printf("nError reading from Client 1: %m", errno);
                clients[i].agent->getRobot()->pauseSensorStream();
                done = true;
            }   //end if error
            //if connection closed, exit
            else if(numRead == 0) {
                printf("nClosing socket");
                close(clients[i].fd);
                done = true;
                i = count;
            }   //end if connection closed
            //if message, call getsendback
            else if(in[0] != '') {
                if(read_mess)
                    std::cout<<"nMessage successfully received from Client "<<clients[i].id<<": "<<in;
                getSendBack(in, clients[i].id);
            }   //end if message
        }   //end if
    }   //end for

    /*CHECK FOR STDIN*/
    //if stdin is ready for reading
    if(FD_ISSET(STDIN_FILENO, &read_flags)) {
        fgets(out, 512, stdin);
        //if changing the view
        if(out[0] == 'v') {
            std::string temp(out);
            char w = temp.substr(2, 1)[0];
            which_display = w;
        }   //end if changing the view
        //else check for writing
        else {
            for(int i=0;i<count;i++) {
                //if a socket is reading for writing
                if(FD_ISSET(clients[i].fd, &write_flags)) {
                    //clear set
                    FD_CLR(clients[i].fd, &write_flags);
                    //if not changing the view and begins with a digit or quitting
                    if(is_id(out[0]) || out[0] == 'q') {
                        //create message to send
                        std::stringstream tosend;
                        //if not the quit command
                        if(out[0] != 'q') {
                            //make a temp of out to substr out the client id
                            std::string temp(out);
                            tosend<<"@ "<<temp.substr(2, temp.length() - 2);
                            //std::cout<<"ntosend: "<<tosend.str();
                            //send message to the client
                            numSent = send(get_client_fd(out[0]), tosend.str().c_str(), tosend.str().length(), 0);
                        }   //end if not the quit command
                        //if quit command
                        else {
                            tosend<<"@ q";
                            //std::cout<<"ntosend: "<<tosend.str();
                            //send message to quit to all clients
                            for(int i=0;i<count;i++)
                                numSent = send(clients[i].fd, tosend.str().c_str(), tosend.str().length(), 0);
                        }   //end quit message
                        //if error, exit
                        if(numSent < 0) {
                            printf("nError sending to Client %cnMessage: %snError message %m", out[0], out, errno);
                            done = true;
                            i = count;
                        }   //end if error
                        //if no error and sent_mess is true, print message
                        else if(numSent > 0 && sent_mess)
                            std::cout<<"nMessage successfully sent to Client "<<out[0]<<": "<<tosend.str();
                    }   //end if not changing view and begins with a digit or quitting
                    //wait for message to get there, then clear
                    usleep(10000);
                    memset(&out, 0, 512);
                }   //end if
            }   //end for
        }   //end if not changing view
    }   //end if stdin ready for reading
}   //end while
}   //END COMMUNICATE

我认为问题在哪里在getSendBack是在最开始-

void TcpServer::getSendBack(char* command, char client_id) {
std::string tempCommand(command);
//std::cout<<"ntempCommand: "<<tempCommand;
//count the number of headers
int num_headers = 0;
for(int i=0;i<tempCommand.length() && num_headers < 2;i++)
    if(tempCommand[i] == '@')
        num_headers++;
//if no message stacking
if(num_headers == 1) {
    //if packet id 1 (update pos/goal/direction)
    if(tempCommand[2] == '1') {
        //get position row
        int prowend = 4;
        while(isdigit(tempCommand[prowend]))
            prowend++;
        std::string p(tempCommand.substr(4, prowend-3));
        int prow = atoi(p.c_str());
        //std::cout<<"nprow: "<<prow;
        //get position column
        int pcolend = prowend+1;
        while(isdigit(tempCommand[pcolend]))
            pcolend++;
        std::string c(tempCommand.substr(prowend, pcolend-prowend));
        int pcol = atoi(c.c_str());
        //std::cout<<"npcol: "<<pcol;
        //get goal row
        int growend = pcolend+1;
        while(isdigit(tempCommand[growend]))
            growend++;
        std::string gr(tempCommand.substr(pcolend, growend-pcolend));
        int grow = atoi(gr.c_str());
        //std::cout<<"ngrow: "<<grow;
        //get goal column
        int gcolend = growend+1;
        while(isdigit(tempCommand[gcolend]))
            gcolend++;
        std::string gc(tempCommand.substr(growend, gcolend-growend));
        int gcol = atoi(gc.c_str());
        //std::cout<<"ngcol: "<<gcol;
        char direction = tempCommand[tempCommand.length()-1];
        //std::cout<<"ndirection: "<<direction;

        Position temp_pos(prow, pcol);
        Position temp_goal(grow, gcol);
        //lock
        pthread_mutex_lock(&mutex_agent);
        //set the new information for the client
        get_client(client_id).agent->setPosition(temp_pos);
        get_client(client_id).agent->setGoal(temp_goal);
        get_client(client_id).agent->setDirection(direction);
        //unlock
        pthread_mutex_unlock(&mutex_agent);
    }   //end if new goal

    //else if packet id 2 (change sensor)
    else if(tempCommand[2] == '2') {
        int idend = 4;
        while(isdigit(tempCommand[idend]))
            idend++;
        std::string temp(tempCommand.substr(4, idend-2));
        //std::cout<<"ntemp: "<<temp;
        int id = atoi(temp.c_str());
        //if valid id value, set new current sensor
        if(id > 6 && id < 43)
            get_client(client_id).agent->getRobot()->setCurrentSensor(id);
        else
            std::cout<<"n"<<id<<" is Invalid id";
    }   //end if new sensor
    //else if 5, quit
    else if(tempCommand[2] == '5')
        done = true;
}   //end if 1 header
//else if stacking
else
    std::cout<<"nSTACKED MESSAGE: "<<tempCommand;
}   //END GETSENDBACK

是什么:"main.cpp:230", tcpserver.cpp:304 ?他们似乎就是问题所在

我解决了这个问题。我有一个文件描述符数组,我在整个运行时分别向它们发送和接收消息。但我使用相同的缓冲区来接收来自每个人的消息。一旦我使用一个单独的缓冲区来接收来自每个文件描述符的消息,我就不再得到来自Valgrind的错误。