0

我正在编写一个简单的应用程序,它将某个目录中的所有文件输出到控制台。为了实现这一点,我在函数中动态分配内存PathCreator()并返回指向该内存的指针。我不知道如何在GetAllFiles(). 当我使用下面的代码时,我得到一个堆栈溢出异常。我怎样才能解决这个问题?请不要让我使用不需要动态分配内存的东西,我只想修复我的代码。

#include "stdafx.h"
#include <windows.h>
#include <iostream>
wchar_t *PathCreator(wchar_t *dir, wchar_t *fileName);
int is_directory(wchar_t *p)
{
    wchar_t *t = PathCreator(p,L"\\");
    WIN32_FIND_DATA file;
    HANDLE search_hendle = FindFirstFile(t, &file);
    long error = GetLastError();
    if(error == 267)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

wchar_t *PathCreator(wchar_t *dir, wchar_t *fileName)
{
    wchar_t* path = 0;
    int size = 0;
    wchar_t *d = dir;
    wchar_t *f = fileName;
    while(*d != '\0')
    {
        d++;
        size++;
    }
    while(*f != '\0')
    {
        f++;
        size++;
    }
    path = new wchar_t[(size+=3) * sizeof(wchar_t)];
    int j = 0;
    while(j < size)
    {
        path[j] = '\0';
        j++;
    }
    int i;
    i = 0;
    while(*dir != '\0')
    {
        path[i] = *dir;
        i++;
        dir++;
    }
    path[i++] = '\\';
    wchar_t *t = fileName;  
    while(*t != '\0')
    {
        path[i] = *t;
        i++;
        t++;
    }
    path[i] = '\0';
    return path;
} 

void GetAllFiles(wchar_t* dir)
{
    wchar_t *p = 0;

    int i = 0;
    WIN32_FIND_DATA file;
    wchar_t *t = PathCreator(dir, L"*");
    HANDLE search_hendle = FindFirstFile(t, &file);
    if(search_hendle)
    {

        do
        {
            p = PathCreator(dir,file.cFileName);
            if(!is_directory(p))
            {
                std::wcout << p << std::endl;
            }
            else
            {
                GetAllFiles(p);
            }
            delete [] p;
        }
        while(FindNextFile(search_hendle, &file));

    }
    delete [] t;
    FindClose(search_hendle);
}


int _tmain(int argc, _TCHAR* argv[])
{
    GetAllFiles(L"C:\\Users");
}
4

2 回答 2

8

所以你有了 ”。” 和“..”在您的目录搜索中。

第一个条目是“.”,所以:

p = PathCreator(dir, file.cFilename)

产量:

"C:\Users\."

然后是下一行:

if (!is_directory(p))

总是错误的,所以它只是不断递归到:

GetAllFiles(p)

永远......或者直到你的堆栈爆炸,以先到者为准;-)

我建议明确检查“。” 和“..”并跳过这些条目(MFC 和 Qt 等也有很好的目录处理类,但我认为你想这样做)。

我的修改:

    do
    {

        // I added this - guess I can't embolden code text
        if (wcscmp(file.cFileName,L".") == 0 || wcscmp(file.cFileName,L"..")==0)
            continue;

        p = PathCreator(dir,file.cFileName);
        if(!is_directory(p))
        {
            std::wcout << p << std::endl;
        }
        else
        {
            GetAllFiles(p);
        }
        delete [] p;
    }
    while(FindNextFile(search_hendle, &file));
于 2012-10-16T19:56:19.877 回答
2

你再次尝试使用C代替,C++你还在使用wcout?!没问题,您是程序员,我相信您有理由这样做!但是内存管理C要困难得多C++,你应该有一些使用它的技能。这是一个完整的工作代码,但正如您所见,它比使用标准容器和字符串的 C++ 版本更难管理、使用和理解,所以如果您被允许使用 C++(当您使用时wcout),那么请使用它的 C++ 版本以方便使用:

#include <Windows.h>
/*! \brief Merge \a folder and \a filename into a newly allocate memory and
 * return it to the caller. Use free to free returned memory!
 */
wchar_t* PathCreator( wchar_t const* folder, wchar_t const* filename )
{
    wchar_t* res;
    size_t i, len, folderLen = wcslen( folder ), filenameLen = wcslen( filename );
    len = folderLen + filenameLen;
    if( folder[folderLen - 1] != '\\' ) ++len;
    ++len;  // for \0

    res = (wchar_t*) malloc( sizeof(wchar_t) * len );
    if( !res ) return NULL;

    wcscpy_s( res, len, folder );
    /* Remove possible wide card at end of folder */
    for( i = folderLen; i--; ) {
        if( res[i] == '*' || res[i] == '?' ) {
            res[i] = 0;
            --folderLen;
        } else {
            break;
        }
    }
    if( res[folderLen - 1] != '\\' ) wcscat_s( res, len, L"\\" );
    wcscat_s( res, len, filename );

    return res;
}
/*! \brief Free memory that returned by \ref GetAllFiles
 */
void FreeAllFilesMemory( wchar_t** p )
{
    wchar_t** tmp = p;
    if( !p ) return ;
    while( *tmp ) free( *tmp++ );
    free( p );
}
wchar_t** AddToArray( wchar_t** p, size_t* pAllocated, size_t* pUsed, wchar_t* s )
{
    if( *pUsed >= *pAllocated ) {
        size_t newAlloc = *pAllocated * 3 / 2;  // Grow by 1.5
        if( newAlloc < 16 ) newAlloc = 16;
        p = (wchar_t**) realloc( p, newAlloc * sizeof(wchar_t*) );
        if( !p ) return NULL;
        *pAllocated = newAlloc;
    }

    p[*pUsed] = s;
    ++*pUsed;
    return p;
}
wchar_t** GetAllFilesImpl( wchar_t const* folder, wchar_t** res, size_t* pAllocated, size_t* pUsed )
{
    HANDLE hSearch;
    WIN32_FIND_DATAW fileinfo;
    size_t allocatedMemory = 0;

    hSearch = FindFirstFileW( folder, &fileinfo );
    if( hSearch != INVALID_HANDLE_VALUE ) {
        do {
            wchar_t* sFileName, ** tmp, sTmp[ 1024 ];
            /* ignore ., .. */
            if( !wcscmp(fileinfo.cFileName, L".") ||
                !wcscmp(fileinfo.cFileName, L"..") )
                continue;
            sFileName = PathCreator( folder, fileinfo.cFileName );
            wprintf( L"%s\n", sFileName );  /* Print result */
            tmp = AddToArray( res, pAllocated, pUsed, sFileName );
            if( !tmp ) return FreeAllFilesMemory(res), NULL;
            res = tmp;
            if( fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
                wcscpy_s( sTmp, sFileName );
                wcscat_s( sTmp, L"\\*" );
                tmp = GetAllFilesImpl( sTmp, res, pAllocated, pUsed );
                if( !tmp ) return NULL;
                res = tmp;
            }
        } while( FindNextFileW(hSearch, &fileinfo) );
        FindClose( hSearch );
    }
    return res;
}
/*! \brief List all files that match a pattern and return it as an array of
 * wide strings, free result using \ref FreeAllFilesMemory
 */
wchar_t** GetAllFiles( wchar_t const* folder )
{
    size_t nAllocated = 0, nUsed = 0;
    wchar_t** res = GetAllFilesImpl( folder, NULL, &nAllocated, &nUsed );
    if( res ) {
        /* to indicate end of result add a NULL string */
        wchar_t** tmp = AddToArray( res, &nAllocated, &nUsed, NULL );
        if( !tmp ) return FreeAllFilesMemory(res), NULL;
        res = tmp;
    }
    return res;
}
于 2012-10-16T20:29:38.273 回答