Frage

I am trying to access all files in a directory and do some thing on the files under this and the subsequent directories. For this operation I used dirent.h with windows and it manages to get all the files and open and close these files. My problem is, when i try to read some something from them and write to another, as shown below, i get the error shown at the end.

Here is the code:

#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;
}

It manages to open and read the first file but after the first file it will show the following error and open dbgheap.c

HEAP[direntdir.exe]: Invalid address specified to RtlValidateHeap( 002C0000, 002C5718 ) Windows has triggered a breakpoint in direntdir.exe.

This may be due to a corruption of the heap, which indicates a bug in direntdir.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while direntdir.exe has focus.

The output window may have more diagnostic information.

EDIT: corrected the errors with the buf variables.

Now i get

Debug Assertion Failed!

... Expression:(buffer!=NULL) ...

War es hilfreich?

Lösung

You have two variables named buf:

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

The latter hides the first and latter is free()d, even though it was created using new, and then reused without being reallocated. The latter is also used as an argument to fread(). Rename char* buf and possibly make it local to the function and just use a stack allocated buffer:

char fread_buffer[51];

EDIT:

char* buffer never has memory allocated for it before it used in fread() so the call to fread() could be writing anywhere in memory. Change to:

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

and don't call free() on buffer if it is declared this way.

Also, to simplify things just declare buf as:

struct stat buf;

and call stat():

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

Making these two changes will remove all dynamic memory management from the code.

EDIT 2:

This if is an assignment, not an inequality check:

if(test_file=NULL)
    fclose(test_file);

should be:

if(NULL != test_file)
    fclose(test_file);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top