CodeInside
@CodeInside

Почему появляется ошибка при выделении памяти?

Суть задачи заключается в поиске файлов и папок по заданным критериям. Использовал паттерн компоновщик.
// path.h
class Path
{
public:
	Path();
	Path(const std::string&);
	~Path();

	void setPath(const std::string&);
	std::string toString() const;

	bool exists() const;
	bool isAccess() const;

	bool isFile() const;
	bool isDirectory() const;
	bool isRootDirectory() const;
	bool isFullPath() const;

	int calculateCountOfObjectsInside();	// Only for directories (object is a file or directory);  not includes a directory of "." and ".."

	/**
	*	И ещё множество методов, но не столь важно.
	*/

private:
	std::string path_;	
};

  // FileSystemElement.h
class FileSystemElement
{
public:
	FileSystemElement(const Path& path);

	__time64_t getTimeCreate();
	__time64_t getTimeAccess();
	__time64_t getTimeWrite();
	virtual _fsize_t calculateSize() = 0;
	std::string getName();
	std::string getPath();

	virtual std::vector<FileSystemElement*> search(const std::string& elementName, const std::string& phrase, const bool& recursively) = 0;

protected:
	Path path_;
	__time64_t  timeCreate_;    /* -1 for FAT file systems */
	__time64_t  timeAccess_;    /* -1 for FAT file systems */
	__time64_t  timeWrite_;
	_fsize_t    size_;
	std::string name_;

	void initElement(const _finddata_t&);
};

  // Directory.h
class Directory : public FileSystemElement
{
public:
	Directory(const Path&);
	~Directory();

	std::vector<FileSystemElement*> getChilds();
	std::vector<FileSystemElement*> search(const std::string& elementName, const std::string& phrase, const bool& recursively);
	_fsize_t calculateSize();

	void reloadChilds();

private:
	std::vector<FileSystemElement*> childs_;
	bool childsAreInitialized;

	void initializeChilds();
};

  // File.h
class File : public FileSystemElement
{
public:
	File(const Path&);

	std::vector<FileSystemElement*> search(const std::string& elementName, const std::string& phrase, const bool& recursively);
	_fsize_t calculateSize();

private:
	std::string format_;
};

// Метод поиска в file.cpp
  std::vector<FileSystemElement*> File::search(const std::string& elementName, const std::string& phrase, const bool& recursively)
{
	bool fitsSearchParams = false;

	std::string thisFileFormat;
	thisFileFormat.append(name_, name_.find(wchar_t('.')) + 1, name_.size());

	/**
	*	Request: "*.[format]"
	*/
	if (elementName.find('.') != std::string::npos &&
		elementName[0] == '*') {
		std::string formatFromRequest;
		formatFromRequest.append(elementName, elementName.find('.') + 1, elementName.size());

		if (thisFileFormat == formatFromRequest)
			fitsSearchParams = true;
	}

	/**
	*	Request: "*.*"
	*/
	if (elementName == "*.*")
		fitsSearchParams = true;		

	/**
	*	Request: "[name].[format]" or "[name]"
	*/

	if (elementName.find('.') != std::string::npos &&
		elementName.find('*') == std::string::npos &&
		elementName.find('?') == std::string::npos)
		if (name_ == elementName)
			fitsSearchParams = true;

	if(name_.find(elementName) != std::string::npos)
		fitsSearchParams = true;
		

	/**
	*	Request: "?.[format]"
	*/

	/**
	*	Request: "?.?"
	*/

	/**
	*	Request: "[name].?"
	*/


	std::vector<FileSystemElement*> result;

	if (fitsSearchParams) {
		result.push_back(new File(path_));
	}

	/**
	*	Phrase handling.
	*/
	if (thisFileFormat == "txt" && !phrase.empty())
		if (!textFileContainsPhrase(path_, phrase))
			fitsSearchParams = false;

	return result;
}



bool textFileContainsPhrase(const Path& path, const std::string& phrase)
{
	bool fileContainsPhrase = false;

	std::ifstream ifs(path.toString().c_str(), std::ifstream::in);

	char* str = new char[PHRASE_READING_BUFF_SIZE];

	while (!ifs.eof())	{
		ifs >> str;
		if (std::string(str).find(phrase) != std::string::npos) {
			fileContainsPhrase = true;
			break;
		}	
	}

	ifs.close();
	delete[] str;

	return fileContainsPhrase;
}

  // Поиск в Directory.cpp
std::vector<FileSystemElement*> Directory::search(const std::string& elementName, const std::string& phrase, const bool& recursively)
{
	reloadChilds();

	std::vector<FileSystemElement*> result;
	
	if (recursively || path_.isRootDirectory())
		for (auto child : childs_)
			for (auto element : child->search(elementName, phrase, recursively))
				result.push_back(element);

	if (name_.find(elementName) != std::wstring::npos)
		result.push_back(new Directory(path_));
	
	return result;
}

  void Directory::reloadChilds()
{
	//if(!childs_.empty())
	for (auto element : childs_)
		delete element;

	initializeChilds();
}

  void Directory::initializeChilds()
{
	if (!childsAreInitialized) {
		int nChilds = path_.calculateCountOfObjectsInside();

		if (nChilds == 0)
			return;

		childs_.reserve(path_.calculateCountOfObjectsInside());

		std::string find = path_.toString();

		find += "\\*";

		_finddata_t* data = new _finddata_t;
		int handle = _findfirst(find.c_str(), data);
		int result = handle;
		while (result != -1) {
			if (strcmp(data->name, ".") == 0 || strcmp(data->name, "..") == 0) {
				result = _findnext(handle, data);
				continue;
			}

			Path internalObject(path_.toString() + '\\' + data->name);

			if (internalObject.isFile())
				childs_.push_back(new(std::nothrow) File(internalObject));
			else
				childs_.push_back(new(std::nothrow) Directory(internalObject));

			result = _findnext(handle, data);
		}
		_findclose(handle);
		delete data;

		childsAreInitialized = true;
	}
}


Пограмма падает в методе void Directory::initializeChilds() при втором(не знаю почему именно втором) СТАТИЧЕСКОМ выделении памяти. Падает только когда много уровней вложенности. Писал несколько версий этого метода (заменял динамическим выделением памяти) - всегда одна и та же ошибка на одном и том же объекте файловой системы. Я подовзреваю, что проблема в том, что программа использовала всю выделенную для неё память и поэтому статически уже не резервируется. Ошибка при дебаге 4962549e69c74691ba22c43d8b57663c.jpg
Ошибка при выполненииec7c7d8da3f84de3b4fcb9652e74a763.jpg
Можете помочь, ибо я без понятия как решить эту проблему?
Думал о замене компоновщика на обычную рекурсию. Таким образом не будет объектов классов FileSystemElement*, множества векторов ... Но не хочется уходить с компоновщика и понижать уровень абстракции кода.
  • Вопрос задан
  • 174 просмотра
Решения вопроса 1
@Mercury13
Программист на «си с крестами» и не только
1. Чему равняется nChilds?
2. Сам-то CalculateCountOfObjectsInside() в порядке?
3. Случайно наша система не ходит по каталогам «.» и «..»?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы