mikeizbicki / ucr-cs100

open source software construction course
Other
486 stars 407 forks source link

Valgrind possible leaks? #1009

Closed plusEight closed 9 years ago

plusEight commented 9 years ago

Running valgrind on my executable reveals that I have 70 bytes possibly lost. I tried to interpret what I could from valgrind and it looks like it is finding issues within the following functions

main workcommand filterstr

filterstr is called within my workcommand function, which is called in my main. So I believe that filterstr might be the culprit for memory leaks in all three functions. However, I cannot seem to find anything that might relate to memory issues in that function.

Any idea where the leaks are coming from?

Here is the report with tags --leak-check=full bin/rshell used.

==8908== 29 bytes in 1 blocks are possibly lost in loss record 5 of 6
==8908==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8908==    by 0x4EF13B8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==8908==    by 0x4EF1F7A: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==8908==    by 0x4EF25FB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==8908==    by 0x4023B8: filterstr(std::string) (in /home/ping/Documents/Github/rshell/bin/rshell)
==8908==    by 0x403080: workcommand(std::string) (in /home/ping/Documents/Github/rshell/bin/rshell)
==8908==    by 0x403654: main (in /home/ping/Documents/Github/rshell/bin/rshell)
==8908== 
==8908== 41 bytes in 1 blocks are possibly lost in loss record 6 of 6
==8908==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8908==    by 0x4EF13B8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==8908==    by 0x4EF1F7A: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==8908==    by 0x4EF2013: std::string::reserve(unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==8908==    by 0x4EAD0FE: std::basic_istream<char, std::char_traits<char> >& std::getline<char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==8908==    by 0x403635: main (in /home/ping/Documents/Github/rshell/bin/rshell)
==8908== 
==8908== LEAK SUMMARY:
==8908==    definitely lost: 0 bytes in 0 blocks
==8908==    indirectly lost: 0 bytes in 0 blocks
==8908==      possibly lost: 70 bytes in 2 blocks
==8908==    still reachable: 48 bytes in 4 blocks
==8908==         suppressed: 0 bytes in 0 blocks
==8908== Reachable blocks (those to which a pointer was found) are not shown.
==8908== To see them, rerun with: --leak-check=full --show-leak-kinds=all

filterstr's job returns a filtered string that eliminates all excess spaces from the beginning or end of the userinput. If it finds connectors at the beginning or end of userinput, it returns an empty string and gives the user an error.

Lastly, it reformats all connectors in the userinput string so I can easily parse them later.

string filterstr(const string userin){
    string newstr = userin.substr(0, userin.find('#'));
    if(!newstr.empty()){
        while(newstr[0]==' '){
            newstr.erase(0,1);  
        }
        if(newstr[0]=='>' || newstr[0]=='<' || newstr[0]=='|' || newstr[0]=='&'){
            pout()<<"\'"<<newstr[0]<<"\' "<< "cannot be at the start of your command."<<endl;
            return "";
        }
        if(newstr.empty())
            return newstr;
        while(1){
            if(newstr.at(newstr.size()-1)==' '){
                newstr.resize(newstr.size()-1); 
            }
            else break;
        }
        if(newstr.at(newstr.size()-1)==';' || newstr.at(newstr.size()-1)=='|' || newstr.at(newstr.size()-1)=='&'|| newstr.at(newstr.size()-1)=='<'|| newstr.at(newstr.size()-1)=='>'){
            pout()<<"\'"<<newstr.at(newstr.size()-1)<<"\' "<< "cannot be at the end of your command."<<endl;
            return "";
        }   
    }

    boost::replace_all(newstr, "<", " < ");
    boost::replace_all(newstr, ">", " > ");
    boost::replace_all(newstr, ">  >", " >> ");
    boost::replace_all(newstr, "|", " | ");
    boost::replace_all(newstr, "|  |", " || ");
    boost::replace_all(newstr, "&&", " && ");
    boost::replace_all(newstr, ";", " ; ");

    return newstr;
}
tristanzickovich commented 9 years ago

987

Mike said he is only concerned with "definitely lost" and major errors

plusEight commented 9 years ago

Thanks

kavj commented 9 years ago

This happens sometimes when the objects themselves allocate heap memory. They do this if size is unknown at compile time, and valgrind is somewhat cautious. If the amounts were very large, it could be compensated for by manually shrinking the buffers of those objects. String and vector have both clear and shrink_to_fit options in C++11 and I think a couple of the prior standards.