内存泄漏,而不使用C ++中的new运算符

时间:2015-10-26 08:18:05

标签: c++ memory-leaks

我目前正在为我的班级重新创建一个基本的linux shell,而且即使没有使用new运算符,我也遇到了valgrind检测到内存泄漏的问题。我不确定在哪里查看,我无法从valgrind错误消息中做出任何反应。如果有人知道内存泄漏的来源,那将非常感激。谢谢!

==26432== 
==26432== HEAP SUMMARY:
==26432==     in use at exit: 61 bytes in 2 blocks
==26432==   total heap usage: 268 allocs, 266 frees, 28,546 bytes allocated
==26432== 
==26432== 29 bytes in 1 blocks are possibly lost in loss record 1 of 2
==26432==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26432==    by 0x4EF1208: 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)
==26432==    by 0x4EF1DCA: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==26432==    by 0x4EF1E63: std::string::reserve(unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==26432==    by 0x4EACF5E: 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)
==26432==    by 0x401895: main (in /home/randyhe/Documents/FALL2015/CS100/rshell/bin/rshell)
==26432== 
==26432== 32 bytes in 1 blocks are possibly lost in loss record 2 of 2
==26432==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26432==    by 0x4EF1208: 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)
==26432==    by 0x4EF2930: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==26432==    by 0x4EF2D47: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==26432==    by 0x401826: main (in /home/randyhe/Documents/FALL2015/CS100/rshell/bin/rshell)
==26432== 
==26432== LEAK SUMMARY:
==26432==    definitely lost: 0 bytes in 0 blocks
==26432==    indirectly lost: 0 bytes in 0 blocks
==26432==      possibly lost: 61 bytes in 2 blocks
==26432==    still reachable: 0 bytes in 0 blocks
==26432==         suppressed: 0 bytes in 0 blocks
==26432== 
==26432== For counts of detected and suppressed errors, rerun with: -v

我的部分代码在下面。

#include <iostream>
#include <vector>
#include <queue>
#include <utility>
#include <sstream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/wait.h>
#include <errno.h>
#include <limits.h>
#include <pwd.h>

std::pair<std::vector<std::vector<std::string> >, std::queue<std::string> >
    parseInput(std::string s, bool& b);
void check(std::string singleWord, std::string keyword, bool& b, int& index,
        std::vector<std::vector<std::string> >& v, std::queue<std::string>& q);
void executeAll(std::pair<std::vector<std::vector<std::string> >,
    std::queue<std::string> > p);
void printCommands(const std::vector<std::vector<std::string> >& v);
void printConnectors(std::queue<std::string> q);
bool executeSingle(std::vector<std::string>& v);
std::vector<char*> toCharPointers(std::vector<std::string>& v);
char* getHost();

int main()
{
    // Store hostname into character array object hostname
    char hostname[HOST_NAME_MAX];
    int status = gethostname(hostname, HOST_NAME_MAX);
    if(status != 0)
    {
        perror("gethostname failed");
        exit(errno);
    }

    // Store username to login object
    struct passwd *pws;
    pws = getpwuid(geteuid());
    if(pws == NULL)
    {
        perror("getid failed");
        exit(errno);
    }
    std::string login = pws->pw_name;

    for(;;)
    {
        // Output login and hostname
        std::cout << login << "@" << hostname << "$ ";

        // Get user input
        std::string userInput;
        std::getline(std::cin, userInput);

        // If user inputs exit, end program
        if(userInput == "exit")
            exit(0);

        // parsedPair holds the list of commands on its .first, and holds
        // the list of connectors on its .second
        bool correctSyntax = true;
        std::pair<std::vector<std::vector<std::string> >, 
            std::queue<std::string> > parsedPair = 
                parseInput(userInput, correctSyntax);

        if(correctSyntax)
            executeAll(parsedPair);
    }
    return 0;
}

1 个答案:

答案 0 :(得分:4)

如果你知道如何阅读它,你会看到到底发生了什么:

==26432== HEAP SUMMARY:
==26432==     in use at exit: 61 bytes in 2 blocks
==26432==   total heap usage: 268 allocs, 266 frees, 28,546 bytes allocated
==26432== 
==26432== 29 bytes in 1 blocks are possibly lost in loss record 1 of 2
==26432==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26432==    by 0x4EF1208: 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)
==26432==    by 0x4EF1DCA: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==26432==    by 0x4EF1E63: std::string::reserve(unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==26432==    by 0x4EACF5E: 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)
==26432==    by 0x401895: main (in /home/randyhe/Documents/FALL2015/CS100/rshell/bin/rshell)
==26432== 
==26432== 32 bytes in 1 blocks are possibly lost in loss record 2 of 2
==26432==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26432==    by 0x4EF1208: 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)
==26432==    by 0x4EF2930: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==26432==    by 0x4EF2D47: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==26432==    by 0x401826: main (in /home/randyhe/Documents/FALL2015/CS100/rshell/bin/rshell)
==26432==

此:

==26432==    by 0x4EACF5E: 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)

和此:

==26432==    by 0x4EF2D47: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)

是字符串的构造函数(调用new)。

正如评论所说,不要打电话给exit(0);离开你的循环,要么使用breakreturn 0 - 那么最后是本地对象的析构函数将调用main,并释放字符串变量的内存。

请记住,exit不是C ++编译器识别对象发生的事情。它只是一个离开你的程序的巨人goto。它确实做了一些清理,比如关闭文件,但不清理任何对象。这同样适用于setjmp / longjmp对 - C ++不会为那些人清理。

如果要退出从main调用的函数,一种解决方案是抛出main中捕获的异常。

当然,如果您要退出该程序,这种内存泄漏并不可怕 - 它在清理和使代码更复杂之间取得平衡。在这种特殊情况下,它很容易修复,所以我会解决它。但是如果你不得不做出很多很多改动只是为了追逐持续整个程序持续时间的几个对象的内存泄漏,那么这不是一个大问题(它很好)修复它们,但不是必需的)。 BAD内存泄漏是为循环的每次迭代或通常被调用的函数的每次调用泄漏的东西 - 当程序最终拥有它可能的所有内存并导致问题时。