View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000380 | Far Manager | Copy/Move | public | 2007-11-25 23:29 | 2007-12-01 10:54 |
Reporter | alexmitin | Assigned To | alexy | ||
Priority | normal | Severity | major | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Fixed in Version | 1.80 alpha 1 | ||||
Summary | 0000380: Memory leak in ConvertWildcards() | ||||
Description | File: strmix.cpp Line: 234 Function: ConvertWildcards() Context: int ConvertWildcards(const wchar_t *SrcName,string &strDest, int SelectedFolderNameLength) { ... wchar_t *Src = _wcsdup (SrcName); ... } Problem: ----------- The pointer "Src" is never freed. Call stack: ----------- *1 Far.exe!ConvertWildcards(const wchar_t * SrcName=0x00afc0e0, UnicodeString & strDest={...}, int SelectedFolderNameLength=0) 2 Far.exe!ShellCopy::ShellCopyOneFile(const wchar_t * Src=0x00afc0e0, const FAR_FIND_DATA_EX & SrcData={...}, const wchar_t * Dest=0x00ae9cf0, int KeepPathPos=0, int Rename=0) 3 Far.exe!ShellCopy::CopyFileTree(const wchar_t * Dest=0x00ae9cf0) 4 Far.exe!ShellCopy::ShellCopy(Panel * SrcPanel=0x00aebc68, int Move=0, int Link=0, int CurrentOnly=0, int Ask=1, int & ToPlugin=0, const wchar_t * PluginDestPath=0x00000000) 5 Far.exe!FileList::ProcessCopyKeys(int Key=65652) 6 Far.exe!FileList::ProcessKey(int Key=65652) 7 Far.exe!FilePanels::ProcessKey(int Key=65652) 8 Far.exe!Manager::ProcessKey(unsigned long Key=65652) 9 Far.exe!Manager::ProcessMainLoop() 10 Far.exe!Manager::EnterMainLoop() 11 Far.exe!MainProcess(const wchar_t * lpwszEditName=0x009f48f0, const wchar_t * lpwszViewName=0x009f49a8, const wchar_t * lpwszDestName1=0x009f4a60, const wchar_t * lpwszDestName2=0x009f4b18, int StartLine=-1, int StartChar=-1, int RegOpt=0) 12 Far.exe!wmain(int Argc=1, wchar_t * * Argv=0x009f54f0) 13 Far.exe!__tmainCRTStartup() 14 Far.exe!wmainCRTStartup() To reproduce follow these steps: 1) Run the FAR under debugger 2) Put a breakpoint on the following line in the ConvertWildcards() function: wchar_t *Src = _wcsdup (SrcName); 3) Copy any file using F5 in FAR Manager. 4) After the breakpoint hit step through the code. | ||||
Additional Information | FAR 1.80 alpha 1 build 359 | ||||
Tags | No tags attached. | ||||
Build | 368 | ||||
|
Проще всего решается так: [diff] Index: strmix.cpp =================================================================== --- strmix.cpp (revision 1323) +++ strmix.cpp (working copy) @@ -231,7 +231,8 @@ wchar_t *PartAfterFolderName; //BUGBUG string wchar_t *PartBeforeName; //BUGBUG string - wchar_t *Src = _wcsdup (SrcName); + string SrcTmp(SrcName); + wchar_t *Src = SrcTmp.GetBuffer(); //char PartBeforeName[NM],PartAfterFolderName[NM]; DestNamePtr = strDest.GetBuffer ((int)(strDest.GetLength()+StrLength(SrcName)+1)); //??? [/diff] |
|
Нашел ещё один лик в этой же функции: PartAfterFolderName тоже нигде не удаляется. Подумал, что реализация на строках в этой ситуации расточительна, поэтому предлагаю диф решения этих проблем на гвардах, и файл с реализацией гвардов (ScopedGuards.hpp). [diff] Index: strmix.cpp =================================================================== --- strmix.cpp (revision 1335) +++ strmix.cpp (working copy) @@ -38,6 +38,7 @@ #include "fn.hpp" #include "plugin.hpp" #include "lang.hpp" +#include "ScopedGuards.hpp" string &InsertCommas(unsigned __int64 li,string &strDest) { @@ -229,9 +230,9 @@ wchar_t *DestNamePtr, *SrcNamePtr; const wchar_t *CurWildPtr; - wchar_t *PartAfterFolderName; //BUGBUG string + ScoredWDup PartAfterFolderName; //BUGBUG string wchar_t *PartBeforeName; //BUGBUG string - wchar_t *Src = _wcsdup (SrcName); + ScoredWDup Src(_wcsdup (SrcName)); //char PartBeforeName[NM],PartAfterFolderName[NM]; DestNamePtr = strDest.GetBuffer ((int)(strDest.GetLength()+StrLength(SrcName)+1)); //??? @@ -247,7 +248,7 @@ if (SelectedFolderNameLength!=0) { - PartAfterFolderName = _wcsdup (Src+SelectedFolderNameLength); + PartAfterFolderName.reset(_wcsdup (Src+SelectedFolderNameLength)); Src[SelectedFolderNameLength]=0; } @@ -615,7 +616,7 @@ string &RemoveChar(string &strStr,wchar_t Target,BOOL Dup) { wchar_t *Ptr = strStr.GetBuffer (); - wchar_t *Str = Ptr, *StrBegin = Ptr, Chr; + wchar_t *Str = Ptr, Chr; while((Chr=*Str++) != 0) { if(Chr == Target) [/diff] |
2007-12-01 07:06
|
ScopedGuards.hpp (2,716 bytes)
#ifndef __SCOPEDGUARD_HPP__ #define __SCOPEDGUARD_HPP__ /* ScopedGuards.hpp */ /* Copyright (c) 1996 Eugene Roshal Copyright (c) 2000 Far Group All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ template <class T, class Traits> struct ScoredBase { ScoredBase(): elt(0) {} explicit ScoredBase(T *elt): elt(elt) {} ~ScoredBase() {Traits::dispose(elt);} const T *get() const {return elt;} T *get() {return elt;} operator const T *() const {return get();} operator T *() {return get();} void swap(ScoredBase<T, Traits>& other) { T *tmp = elt; elt = other.elt; other.elt = tmp; } void reset(T *newElt) { if (elt == newElt) return; ScoredBase<T, Traits> other(newElt); swap(other); } T * release() { T *tmp = elt; elt = 0; return tmp; } private: T *elt; ScoredBase(const ScoredBase&); ScoredBase& operator=(const ScoredBase&); }; template <class T> struct NewTraits { static void dispose(T *elt) {delete elt;} }; template <class T> struct ScopedGuard : ScoredBase<T, NewTraits<T> > { ScopedGuard(T *elt): ScoredBase<T, NewTraits<T> >(elt) {} }; void __cdecl xf_free(void *); struct FreeTraits { static void dispose(void *elt) {xf_free(elt);} }; typedef ScoredBase<wchar_t, FreeTraits> ScoredWDup; #endif //__SCOPEDGUARD_HPP__ |
|
368 |
Date Modified | Username | Field | Change |
---|---|---|---|
2007-11-25 23:29 | alexmitin | New Issue | |
2007-11-27 14:00 | Tonal | Note Added: 0000879 | |
2007-12-01 07:06 | Tonal | Note Added: 0000893 | |
2007-12-01 07:06 | Tonal | File Added: ScopedGuards.hpp | |
2007-12-01 07:28 | alexy | Project | Known Error => Far Manager |
2007-12-01 07:32 | alexy | Status | new => assigned |
2007-12-01 07:32 | alexy | Assigned To | => alexy |
2007-12-01 10:54 | alexy | Build | => 368 |
2007-12-01 10:54 | alexy | Status | assigned => closed |
2007-12-01 10:54 | alexy | Note Added: 0000896 | |
2007-12-01 10:54 | alexy | Resolution | open => fixed |
2007-12-01 10:54 | alexy | Fixed in Version | => 1.80 alpha 1 |