что не так со следующим рекурсивным поиском в каталоге и открытием файла? - PullRequest
0 голосов
/ 03 марта 2012

Я пытаюсь получить доступ ко всем файлам в каталоге и что-то сделать с файлами в этом и последующих каталогах. Для этой операции я использовал dirent.h с окнами, и ему удается получить все файлы и открыть и закрыть эти файлы. Моя проблема в том, что когда я пытаюсь прочитать что-то из них и написать другому, как показано ниже, я получаю сообщение об ошибке, показанное в конце.

Вот код:

#include <iostream>
#include <cstring>
#include <sys/stat.h>
#include <dirent.h>
FILE *test_file;
char buffer[51];
void listdir(const char *path) 
{
  struct dirent *entry;
  DIR *dp;

  //std::cout << "Dir: " << path << "\n";

  if(dp = opendir(path))
  {
    struct stat buf ;
    FILE *input_file;

    while((entry = readdir(dp)))
    {
        std::string p(path);
        p += "\\";
        p += entry->d_name;
        char fpath[250];
        //strcpy(fpath,path);
        if(!stat(p.c_str(), &buf))
        {
            if(S_ISREG(buf.st_mode))
            {
                std::cout << "    File: " << entry->d_name << "\n";
                sprintf(fpath,"%s\\%s",path,entry->d_name);
                input_file=fopen(fpath,"r+b");
                test_file=fopen("test_test.txt","a+b");
                if(input_file==NULL)
                {
                std::cout<<"\n Could not open\n"<<entry->d_name<<std::endl;
                continue;
                }
                if(test_file==NULL)
                    goto z;
                else 
                {
                    std::cout<<"\n Successfully Opened\n"<<fpath;
                    fread(buffer,50,1,input_file);
                    fprintf(test_file,"\n\n%s\n\n",fpath);
                    fwrite(buffer,50,1,test_file);

                    fclose(input_file);
                     fclose(test_file);
                    // free(buffer);
                }
z:
                if(test_file=NULL)
                fclose(test_file);
            }
            if(S_ISDIR(buf.st_mode) &&  
         // the following is to ensure we do not dive into directories "." and ".."
                      strcmp(entry->d_name, ".")  && strcmp(entry->d_name, "..") )
            {
                listdir(p.c_str());
            }
        }
        else
            std::cout << "ERROR in stat\n";
    }
   // delete buf;
    closedir(dp);
  }
  else
    std::cout << "ERROR in opendir\n";
  fclose(test_file);
}

int main(int argc, char **argv) 
{
  listdir(argv[1]);
  return 0;
}

Ему удается открыть и прочитать первый файл, но после первого файла отобразится следующая ошибка и откроется dbgheap.c

HEAP [direntdir.exe]: неверный адрес, указанный для RtlValidateHeap ( 002C0000, 002C5718) Windows запустила точку останова в direntdir.exe.

Это может быть связано с повреждением кучи, что указывает на ошибку в direntdir.exe или любую из загруженных им библиотек DLL.

Это также может быть связано с тем, что пользователь нажимает клавишу F12, когда direntdir.exe имеет фокус.

В окне вывода может быть больше диагностической информации.

EDIT: исправил ошибки с помощью переменных buf .

Теперь я получаю

Ошибка отладочного подтверждения!

... Выражение: (буфер! = NULL) ...

1 Ответ

2 голосов
/ 03 марта 2012

У вас есть две переменные с именем buf:

char* buf;
...
struct stat *buf = new struct stat;

Последний скрывает первый и последний - free() d, хотя он был создан с использованием new, а затем повторно использован без перераспределения. Последний также используется в качестве аргумента для fread(). Переименуйте char* buf и, возможно, сделайте его локальным для функции и просто используйте выделенный стеком буфер:

char fread_buffer[51];

EDIT:

char* buffer никогда не выделяла для него память до того, как она использовалась в fread(), поэтому при вызове fread() запись в любую точку памяти возможна. Изменить на:

char buffer[50]; /* as only 50 bytes are read from the file */

и не вызывайте free() на buffer, если он объявлен таким образом.

Кроме того, для упрощения просто объявите buf как:

struct stat buf;

и звоните stat():

if(!stat(p.c_str(), &buf))

Выполнение этих двух изменений приведет к удалению всего динамического управления памятью из кода.

РЕДАКТИРОВАТЬ 2:

Это if является заданием, а не проверкой неравенства:

if(test_file=NULL)
    fclose(test_file);

должно быть:

if(NULL != test_file)
    fclose(test_file);
...