Valgrind 上的内存堆和泄漏总结

Posted

技术标签:

【中文标题】Valgrind 上的内存堆和泄漏总结【英文标题】:Memory Heap and Leak Summary on Valgrind 【发布时间】:2022-01-13 16:58:52 【问题描述】:

我们学校的提交都是通过矩阵使用 valgrind 的,它逐行检查输出。但是,在提交时,我收到“检测到内存错误”。

编译结果:

Success! No errors or warnings...

执行:

Script started, file is student_output.txt
Script started, file is student_output.txt
==110143== Memcheck, a memory error detector
==110143== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==110143== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==110143== Command: ms
==110143==
Loading Data
Library Application:

输入数据时:

Publication Title: e
==111103== Conditional jump or move depends on uninitialised value(s)
==111103==    at 0x404318: sdds::LibApp::search(int, char) (LibApp.cpp:145)
==111103==    by 0x404ABC: sdds::LibApp::removePublication() (LibApp.cpp:329)
==111103==    by 0x404DC1: sdds::LibApp::run() (LibApp.cpp:415)
==111103==    by 0x404F6F: runLibApp(char const*) (LibAppMain_prof.cpp:9)
==111103==    by 0x405084: main (LibAppMain_prof.cpp:20)
==111103==

其他信息

我在添加出版物时也遇到了错误(使用 newPublication() 函数),它位于下面的同一文件中。

==140314== Use of uninitialised value of size 8
==140314==    at 0x404926: sdds::LibApp::newPublication() (LibApp.cpp:282)
==140314==    by 0x404DAA: sdds::LibApp::run() (LibApp.cpp:411)
==140314==    by 0x404F6F: runLibApp(char const*) (LibAppMain_prof.cpp:9)
==140314==    by 0x405084: main (LibAppMain_prof.cpp:20)
==140314==
==140314== Use of uninitialised value of size 8
==140314==    at 0x40493F: sdds::LibApp::newPublication() (LibApp.cpp:284)
==140314==    by 0x404DAA: sdds::LibApp::run() (LibApp.cpp:411)
==140314==    by 0x404F6F: runLibApp(char const*) (LibAppMain_prof.cpp:9)
==140314==    by 0x405084: main (LibAppMain_prof.cpp:20)
==140314==

文件发布在下面。

LibApp.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <iostream>
#include <fstream>
#include <cstring>
#include <iomanip>
#include "LibApp.h"
#include "Book.h"
#include "PublicationSelector.h"

namespace sdds 

int NOLP=0;
int LLRN=0;

      bool LibApp::confirm(const char* message)
      
         Menu conf(message);
         conf<<"Yes";  
         int t_return = conf.run();

         if(t_return) return true;

          return false;

      

      LibApp::LibApp(const char filename[256])
        

         
         m_mainMenu << "Add New Publication" 
         << "Remove Publication" 
         << "Checkout publication from library"
         <<"Return publication to library";
         m_exitMenu << "Save changes and exit" << "Cancel and go back to the main menu";

         strcpy(m_filename, filename);
        

         m_publicationMenu << "Book" << "Publication" ;

         load();
      

      LibApp::~LibApp()
      

         for (int i = 0; i< NOLP ; i++) 
            delete PPA[i];
         
      

      void LibApp::load()

   
         std::cout<<"Loading Data\n";
         
         std::ifstream infile(m_filename);
         char type;
         
         for (int i = 0; infile ; i++) 
            infile >> type;
            infile.ignore();


            
            if (infile) 
            
               if (type == 'P')
                  PPA[i] = new Publication;
               else if (type == 'B')
                  PPA[i] = new Book;
               else std::cout<<"no data\n";

               if (PPA[i] && i < SDDS_LIBRARY_CAPACITY ) 

                  infile >> *PPA[i];

                  LLRN=PPA[i]->getRef();

                  NOLP++;



               

            
            
         
      
        
      
      
      
      void LibApp::save()
         std::cout<<"Saving Data\n";

    
         std::ofstream outfile(m_filename);
       
         
         for (int i = 0; i < NOLP; i++) 
            
            if (PPA[i]->getRef()!=0) 
            
               outfile << *PPA[i] << std::endl;

               
            
            
               
         

      
         

      
      void prnPub(Publication* p[], int size, int ref) 
         int i;
         for (i = 0; i < size; i++) 
            if (ref == p[i]->getRef()) 
               std::cout << *p[i] << std::endl;
               i = size; 
            
         
      

      int LibApp::search(int option,char type)
         
       
         

         PublicationSelector ps("Select one of the following found matches:", 15);

         std::cout<<"Publication Title: ";

         char title[256];

         std::cin.getline(title,256);


         if(option==1)
         
            for (int i = 0; i< NOLP; i++) 
                     
                     if (strstr(*PPA[i],title) && PPA[i]->getRef()!=0 && type==PPA[i]->type())
                        ps << PPA[i]; 
            
         
         else if(option==2)
         
            for (int i = 0; i< NOLP; i++) 
                     
                     if (strstr(*PPA[i],title) && !PPA[i]->onLoan() && PPA[i]->getRef()!=0 && type==PPA[i]->type())
                        ps << PPA[i]; 
            
         
         else if(option==3)
         
            for (int i = 0; i< NOLP; i++) 
                     
                     if (strstr(*PPA[i],title) && PPA[i]->onLoan() && PPA[i]->getRef()!=0 && type==PPA[i]->type())
                        ps << PPA[i]; 
            
         


         int ref = 0;
  
         if (ps) 
            ps.sort(); 
            ref = ps.run(); 
            if (ref) 
               
               prnPub(PPA, NOLP , ref);
            
            else 
               std::cout << "Aborted!\n";
            
         
         else 
            std::cout << "No matches to found!" << std::endl;
         


         return ref;

   
      
         
      
      void LibApp::returnPub()  
      
        
         std::cout<<"Return publication to the library\n";
         int i=m_publicationMenu.run();
         

         char type; 

         if(i==1) type='B';
         else type='P';

         int ref=search(3,type);

         
         if(ref!=0 && confirm("Returning publication?"))
         
            Date date=getPub(ref)->checkoutDate();

            Date today;

            int days=today-date;
            days-=15;

           


            if(days>0)
            
               
               std::cout << std::fixed;
               std::cout << std::setprecision(2);
               std::cout<<"Please pay $"<<float(days)*(0.5)<<" penalty for being "<<days<<" days late!\n";
            

            getPub(ref)->set(0);
            std::cout<<"Publication returned\n";
            m_changed=true;

         



      

      void LibApp::newPublication()
        

         

         if( NOLP >= SDDS_LIBRARY_CAPACITY ) 
         
            std::cout<<"Library is at its maximum capacity!\n";
            return;
         

         std::cout<<"Adding new publication to library\n";

         int i=m_publicationMenu.run();

         Publication *p=nullptr;

         if(i==0)
           std::cout<<"Aborted!\n";
            return;
         
         else if(i==1)
         
            
            p = new Book;
            std::cin >> *p;
         
         else if( i==2 )
         
            p = new Publication;
            std::cin >> *p;
         

         if(std::cin.fail())
         
            std::cout<<"\nAborted!\n";
            exit(0);
         


         if(confirm("Add this publication to library?"))
         
            m_changed = true;

            PPA[NOLP]=p;

            LLRN=PPA[NOLP]->getRef();

            NOLP++;

            std::cout<<"Publication added\n";
         

         if( !*p )
         
            std::cout<<"Failed to add publication!\n";
            delete p;
         

      

      
      Publication* LibApp::getPub(int libRef)
      
         for(int i=0;i<NOLP;i++)
         
            if(libRef==PPA[i]->getRef()) return PPA[i];
         

         return nullptr;

      

      void LibApp::removePublication()
      
         //std::cout<<;

         
            std::cout<<"Removing publication from the library\n";


         int i=m_publicationMenu.run();


         char type; 

         if(i==1) type='B';
         else 
           
            type='P';
         
         int ref=search(1,type);

         
   
         if(ref!=0 && confirm("Remove this publication from the library?"))
         
            m_changed = true;

            getPub(ref)->setRef(0);



            std::cout<<"Publication removed\n";
         
         
      

      void LibApp::checkOutPub()
        

         std::cout<<"Checkout publication from the library\n";
         int i=m_publicationMenu.run();
         char type; 

         if(i==1) type='B';
         else type='P';

         int ref=search(2,type);
         
         if(ref!=0 && confirm("Check out publication?"))
         
            m_changed = true;

            int mn;

            std::cout << "Enter Membership Number: ";

            while (1)
                          
               

               std::cin>>mn;

               if(mn > 9999 && mn <= 99999 ) break;

               std::cout<<"Invalid membership number, try again: ";
            

            getPub(ref)->set(mn);

            std::cout<<"Publication checked out\n";
         


      



      LibApp::LibApp()
      
         m_mainMenu << "Add New Publication" 
         << "Remove Publication" 
         << "Checkout publication from library"
         <<"Return publication to library";

         m_exitMenu << "Save changes and exit" << "Cancel and go back to the main menu";

         load();

      


      

      void LibApp::run()
      
         while(1)
           
            int option =  m_mainMenu.run();

            if( option == 1 )
            
               newPublication();
            
            else if( option == 2 ) 
            
               removePublication();
            
   

     else if( option == 3 )
        
           checkOutPub();
        
        else if( option == 4 )
        
           returnPub();
        
        else if( option == 0 )
        
           if(m_changed)
           
              
              int opn = m_exitMenu.run();

              if( opn == 1 )
              
                 save();
                 break;
              
              else if( opn == 2 )
              
                 ;
              
              else if( opn == 0)
                
                 if(confirm("This will discard all the changes are you sure?"))
                    break;
              

           
           else break;


        

        std::cout<<std::endl;

        
     



     std::cout<<std::endl;
     std::cout<<"-------------------------------------------\n";
     std::cout<<"Thanks for using Seneca Library Application\n";



      


请帮帮我。我今天提交的内容是我知道问题是什么。

【问题讨论】:

Stack Overflow 不是免费的作业帮助服务。 【参考方案1】:

就像错误信息说的那样:

Conditional jump or move depends on uninitialised value(s)
==111103==    at 0x404318: sdds::LibApp::search(int, char) (LibApp.cpp:145)

在 LibApp.cpp 的第 145 行有一个 if 语句(或逻辑上等同于 if 语句的东西),它根据从未初始化为任何值的变量决定采用哪条路径;因此,该 if-test 的行为是未定义的(即 if 可以采用任何一种方式,具体取决于当时该变量的内存位置发生的任意数据)。

因此,您需要查看第 145 行 if-test 中存在的变量,以确定哪些变量没有被预先设置,然后通过确保它们首先被设置来修复错误.

如有必要,您可以添加临时 if-tests 以激发 valgrind 为您提供更多结果:

if (some_suspect_var != 0) fprintf(stderr, “Yea\n”);
else fprintf(stderr, “Nay\n”);

…那么如果你在那个 if 行上得到一个 valgrind 错误,你就知道 some_suspect_var 在那一点上是未初始化的。

【讨论】:

if 语句不是问题。出于某种原因,我的内存没有被动态分配和释放。有人能解决这个问题吗? 解决问题的唯一方法是编译/运行/测试/诊断/重复直到您了解故障,此时您也将了解如何修复它。如果您发布的代码可以由其他人编译,其他人可能会为您执行此操作,但由于它只是部分列表,其他人将无法编译和运行它,这意味着它取决于您弄清楚。

以上是关于Valgrind 上的内存堆和泄漏总结的主要内容,如果未能解决你的问题,请参考以下文章

Unix下C程序内存泄漏检测工具Valgrind安装与使用

MIPS 上的 Valgrind 报告没有堆使用

内存泄漏分析valgrind

Valgrind进行内存泄漏检测

如何修复 Valgrind 日志中的内存泄漏

如何使用 valgrind 查找内存泄漏?