При вызове деструктора объекта p (дальше в коде увидите) выдаёт ошибку 'Debug Assertion Failed. Expression: _CrtIsValidHeapPointer(pUserData). Я так понял, где-то утечка памяти, или некорректная работа с динамической памятью, но никак не могу определить в чём ошибка.
Минимальный вариант кода:
class Path
{
char* path;
public:
Path(char*);
Path(const Path &);
Path(Path &&);
~Path();
Path operator + (const Path &) const;
Path& operator = (const Path &);
Path& operator = (Path &&);
}
Path::Path()
{
path = new char[strlen("C:\\") + 1];
strcpy_s(path, strlen("C:\\") + 1, "C:\\");
}
Path::Path(char* path)
{
this->path = new char[strlen(path) + 1];
strcpy_s(this->path, strlen(path) + 1, path);
}
Path::~Path()
{
delete[] path;
path = nullptr;
}
Path::Path(const Path &obj)
{
path = new char[strlen(obj.path) + 1];
strcpy_s(path, strlen(obj.path) + 1, obj.path);
}
Path::Path(Path &&obj)
{
path = obj.path;
obj.path = nullptr;
}
void main()
{
Path p1("C:\\Program Files\\"), p2("Google Chrome\\Cache");
Path p = p1 + p2;
}
Полная версия:
#include <iostream>
#include <io.h>
#include <conio.h>
using namespace std;
class Path
{
char* path;
public:
Path();
Path(char*);
Path(const Path &);
Path(Path &&);
~Path();
int SetPath(char*);
char* GetPath() const;
bool Exists() const;
bool Exists(char* path, bool overwrite_this_path = false);
bool IsFile() const;
bool IsDirectory() const;
bool IsFullPath() const;
Path operator + (const char &) const;
Path operator + (const Path &) const;
Path& operator += (const char &);
Path& operator += (const Path &);
Path& operator = (const char &);
Path& operator = (const Path &);
Path& operator = (Path &&);
private:
// Removes extra slashes
// Example: (p1 == 'D:\\Data\\', p2 == 'Front-end\\Messages.json').
// User wrote 'path = p1 + '\\' + p2'.
// Then path == 'D:\\Data\\\\Front-end\\Messages.json'.
// This method converts this path in view like 'D:\\Data\\Front-end\\Messages.json'
void CheckSlashes();
};
Path::Path()
{
path = new char[strlen("C:\\") + 1];
strcpy_s(path, strlen("C:\\") + 1, "C:\\");
}
Path::Path(char* path)
{
this->path = new char[strlen(path) + 1];
strcpy_s(this->path, strlen(path) + 1, path);
CheckSlashes();
}
Path::~Path()
{
delete[] path;
path = nullptr;
}
Path::Path(const Path &obj)
{
path = new char[strlen(obj.path) + 1];
strcpy_s(path, strlen(obj.path) + 1, obj.path);
CheckSlashes();
}
Path::Path(Path &&obj)
{
path = obj.path;
obj.path = nullptr;
CheckSlashes();
}
int Path::SetPath(char* path)
{
if (path == nullptr)
{
return 1;
}
delete[] path;
this->path = new char[strlen(path) + 1];
if (this->path == nullptr)
{
return 2;
}
strcpy_s(this->path, strlen(path) + 1, path);
CheckSlashes();
return 0;
}
char* Path::GetPath() const
{
return path;
}
bool Path::Exists() const
{
_finddata_t data;
int descriptor = _findfirst(path, &data);
if (descriptor == -1)
{
return false;
}
else
{
return true;
}
}
bool Path::Exists(char* path, bool overwrite_this_path)
{
if (path == nullptr)
{
return false;
}
if (overwrite_this_path)
{
SetPath(path);
}
_finddata_t data;
int descriptor = _findfirst(path, &data);
if (descriptor == -1)
{
return false;
}
else
{
return true;
}
}
bool Path::IsFile() const
{
_finddata_t data;
int descriptor = _findfirst(path, &data);
if (descriptor == -1)
{
return false;
}
if (!(data.attrib & _A_SUBDIR))
{
return true;
}
else
{
return false;
}
}
bool Path::IsDirectory() const
{
if (path == nullptr)
{
return false;
}
_finddata_t data;
int descriptor = _findfirst(path, &data);
if (descriptor == -1)
{
return false;
}
if (data.attrib & _A_SUBDIR) // data is directory?
{
return true;
}
else
{
return false;
}
}
bool Path::IsFullPath() const
{
bool IsFullPath = false;
if (strlen(path) > 1) // Directory name may consist of one character with
{
IsFullPath = (path[1] == ':'); // Example: 'C:\\Program Files', 'D:\\Data\\Source.cpp'
}
return IsFullPath;
}
Path& Path::operator = (const char &ch)
{
delete[] path;
path = new char[1];
path[0] = ch;
CheckSlashes();
return *this;
}
Path& Path::operator = (const Path &pth)
{
if (this == &pth)
{
return *this;
}
delete[] path;
path = new char[strlen(pth.path) + 1];
strcpy_s(path, strlen(pth.path) + 1, pth.path);
CheckSlashes();
return *this;
}
Path Path::operator + (const char &ch) const
{
Path obj;
int buff_size = strlen(this->path) + 2; // 2 - @ch and '\0'
obj.path = new char[buff_size];
strcpy_s(obj.path, buff_size, this->path);
obj.path[strlen(this->path)] = ch;
obj.path[strlen(this->path) + 1] = '\0';
return obj;
}
// XXX: '\\' beetwen paths (NOT TESTED!)
Path Path::operator + (const Path &pth) const
{
Path obj;
int buff_size = strlen(this->path) + strlen(pth.path) + 1;
obj.path = new char[buff_size];
// Example: 'C:\Program Files' + 'Google Chrome\Cache'
// @obj.path must be 'C:\Program Files\Google Chrome\Cache', not 'C:\Program FilesGoogle Chrome\Cache'
strcpy_s(obj.path, buff_size, this->path);
if (obj.path[strlen(obj.path) - 1] != '\\' && pth.path[0] != '\\')
{
obj += '\\';
buff_size++;
}
// Example: 'C:\Program Files\' + '\Google Chrome\Cache'
// @obj.path must be 'C:\Program Files\Google Chrome\Cache', not 'C:\Program Files\\Google Chrome\Cache'
if (obj.path[strlen(obj.path) - 1] == '\\' && pth.path[0] == '\\')
{
obj.path[strlen(obj.path) - 1] = '\0';
}
strcat_s(obj.path, buff_size, pth.path);
return obj;
}
Path& Path::operator += (const char &ch)
{
char* tmp = new char[strlen(path) + 1];
strcpy_s(tmp, strlen(path) + 1, path);
delete[] path;
path = new char[strlen(tmp) + 2]; // 2 - @ch and '\0'
strcpy_s(path, strlen(tmp) + 2, tmp);
path[strlen(tmp)] = ch;
path[strlen(tmp) + 1] = '\0';
CheckSlashes();
return *this;
}
Path& Path::operator += (const Path &pth)
{
char* tmp = new char[strlen(path) + 1];
strcpy_s(tmp, strlen(path) + 1, path);
delete[] path;
int buff_size = strlen(tmp) + strlen(pth.path) + 1;
path = new char[buff_size];
strcpy_s(path, buff_size, tmp);
strcat_s(path, buff_size, pth.path);
CheckSlashes();
return *this;
}
Path& Path::operator = (Path &&pth)
{
delete[] path;
path = pth.path;
pth.path = nullptr;
CheckSlashes();
return *this;
}
void Path::CheckSlashes()
{
char* ptr = strstr(path, "\\\\");
while(ptr != nullptr)
{
for (int i = 0; i < strlen(ptr); i++)
ptr[i] = ptr[i + 1];
ptr = strstr(path, "\\\\");
}
}
void main()
{
Path p1("C:\\Program Files"), p2("Google Chrome\\Cache");
Path p = p1 + p2;
}