Файл забивается мусором, а при завершении программы происходит аварийная остановка
Пытался написать свой тип файла позволяющий хранить в нём другие файлы.
P.S. Я никогда таким не занимался и делаю это впервые, прошу не швыряться тапками.
Компилируется все замечательно, но падает с ошибкой free(): double free detected in tcache 2 Аварийный останов (стек памяти сброшен на диск)
Всего в проекте 3 файла
main.cpp
#include <iostream>
#include "gymfile.h"
int main()
{
gymdata teser("Hello hi","Some data");
gymdata ass("Another File","Some data");
gymfile test("gamefile.gym",false);
test.writeData(teser);
test.writeData(ass);
test.closeFile();
gymfile testa("gamefile.gym",true);
gymdata popka(testa.getData(0));
}
gymdata.h
#define GYMD
#ifdef GYMD
class gymdata
{
protected:
char name[255];
std::vector <char> rawdata;
public:
char *getData(){
return &rawdata[0];
}
char *getName(){
return name;
}
void setName(char *nname){
strcpy(name,nname);
}
void resize(int size){
rawdata.resize(size);
}
void addbyte(char byte){
resize(rawdata.size()+1);
rawdata[rawdata.size()]=byte;
}
int getArraySize(){
return rawdata.size();
}
gymdata(const char *nname,const char *dt=""){
if(strlen(nname)>255) return;
if (strcmp(dt,"")==0) return;
memset(name,0,255);
strcpy(name,nname);
resize(strlen(dt));
for(int i=0;i<=(strlen(dt));i++){
rawdata[i]=dt[i];
}
}
gymdata(const gymdata &dtb){
rawdata.resize(dtb.rawdata.size()+1);
rawdata = dtb.rawdata;
strcpy(name,dtb.name);
}
};
#endif
gymfile.h
#define GYMF
#ifdef GYMF
#include <fstream>
#include <string>
#include <vector>
#include <cstring>
#include <cstdio>
#include "gymdata.h"
class gymfile{
private:
std::uint16_t files[1024];
char name[255];
FILE *writef;
FILE *readf;
std::string fname;
bool newfile{false};
bool rw;
std::uint16_t getFileStartAddr(int fn){
if (fn>511) return 0;
return files[fn*2];
}
std::uint16_t getFileEndAddr(int fn){
if(fn>511) return 0;
return files[fn*2+1];
}
public:
void openFileWrite(std::string name){
for(int i=0; i<=1024; i++){
files[i]=0;
}
fname=name;
writef = fopen(name.c_str(),"wb");
if(fopen(name.c_str(), "wb")==NULL){
fclose(writef);
return;
}
fseek(writef,0,SEEK_END);
if(2048>ftell(writef)){
newfile=true;
}
fseek(writef,0,SEEK_SET);
}
void openFileRead(std::string name){
for(int i=0; i<=1024; i++){
files[i]=0;
}
readf = fopen(name.c_str(),"rb");
fread(files,sizeof(std::uint16_t),1024,readf);
}
void closeFile(){
if (rw==true) fclose(writef); else
fclose(readf);
}
gymdata getData(int filen){
if (getFileStartAddr(filen)==0) return gymdata("Unknown File","This file not exists");
char filname[255];
fseek(readf,getFileStartAddr(filen),SEEK_SET);
fread(filname,sizeof(char),255,readf);
fseek(readf,256,SEEK_CUR);
std::vector<char> data;
data.resize(getFileEndAddr(filen)-getFileStartAddr(filen));
memset(&data[0],0,data.size());
fread(&data[0],sizeof(char),getFileEndAddr(filen)-getFileStartAddr(filen),readf);
std::cout<<filname<<"\n"<<&data[0]<<std::endl;
return gymdata(filname,&data[0]);
}
gymdata getData(char *filen){
}
void writeData(gymdata dat){
fseek(writef,0,SEEK_SET);
int i=0;
while(i!=1024 && files[i]!=0){
i++;
}
if(i-1<0){
files[i]=2049;
files[i+1]=files[i]+dat.getArraySize()+255;
fseek(writef,2049,SEEK_SET);
} else{
files[i]=files[i-1]+1;
files[i+1]=files[i]+dat.getArraySize()+255;
fseek(writef,files[i-1]+1,SEEK_SET);
}
fwrite(dat.getName(),sizeof(char),255,writef);
fseek(writef,256,SEEK_CUR);
fwrite(dat.getData(),sizeof(char),dat.getArraySize(),writef);
sync();
}
void sync(){
fseek(writef,0,SEEK_SET);
fwrite(files,sizeof(std::uint16_t),1024,writef);
}
gymfile(std::string finame="",bool read=true){
if(read){
rw=false;
}else{
rw=true;
}
if(finame!=""){
if(!read){
openFileWrite(finame);
} else{
openFileRead(finame);
}
}
}
~gymfile(){
closeFile();
}
};
#endif
Ответы (2 шт):
Первая ошибка здесь
resize(strlen(dt));
for(int i=0;i<=(strlen(dt));i++){
rawdata[i]=dt[i];
}
либо в resize(strlen(dt)); на одиницу больше, либо цикл исправьте.
Во вторых - инициализируйте свои переменные. Всегда. Потому что fclose, который получил шальной указатель, не будет работатать
he behavior is undefined if the value of the pointer stream is used after fclose returns.
А также, fclose не любит nullptr.
Вывод - используйте плюсовые классы и функции и будет и понятнее, и проще.
Этот код врятли удастся заставить работать когда-либо. В нём почти в каждой строке есть ошибка.
Причём некоторые специально добавлены: for(int i=0; i<=1024; i++)
Вот списочек, и это только то, что смог найти сам компилятор.
Серьезность Код Описание Проект Файл Строка Состояние подавления
Предупреждение C26447 Функция объявлена как "noexcept", но вызывает функцию "closeFile()", которая может порождать исключения (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 134 Активные
Предупреждение C26440 Функция "main" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 138 Активные
Предупреждение C26440 Функция "gymfile::sync" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 114 Активные
Предупреждение C26440 Функция "gymfile::openFileRead" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 64 Активные
Предупреждение C26440 Функция "gymfile::getFileStartAddr" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 38 Активные
Предупреждение C26440 Функция "gymfile::getFileEndAddr" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 42 Активные
Предупреждение C26440 Функция "gymfile::getData" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 91 Активные
Предупреждение C26440 Функция "gymfile::closeFile" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 72 Активные
Предупреждение C26440 Функция "gymdata::gymdata" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 22 Активные
Предупреждение C26440 Функция "gymdata::getName" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 23 Активные
Предупреждение C26440 Функция "gymdata::getData" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 25 Активные
Предупреждение C26440 Функция "gymdata::getArraySize" может быть объявлена как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 24 Активные
Предупреждение C26495 Переменная "gymfile::files" не инициализирована. Всегда инициализируйте переменную-член (type.6). Test F:\f_prog\repos\Test\Test\Test.cpp 118 Активные
Предупреждение C26455 Конструктор по умолчанию не может выдавать исключения (throw). Объявите его как "noexcept" (f.6). Test F:\f_prog\repos\Test\Test\Test.cpp 118 Активные
Предупреждение C26477 Используйте "nullptr" вместо 0 или NULL (es.47). Test F:\f_prog\repos\Test\Test\Test.cpp 23 Активные
Предупреждение C26477 Используйте "nullptr" вместо 0 или NULL (es.47). Test F:\f_prog\repos\Test\Test\Test.cpp 53 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 40 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 44 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 49 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 66 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 86 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 87 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 88 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 89 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 97 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 101 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 102 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 102 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 105 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 105 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 106 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 106 Активные
Предупреждение C26446 Использовать gsl::at() вместо непроверенного оператора с нижним индексом (bounds.4). Test F:\f_prog\repos\Test\Test\Test.cpp 107 Активные
Предупреждение C6201 Индекс "1024" находится вне диапазона от "0" до "1023" для буфера "this->files", возможно, размещенного в стеке. Test F:\f_prog\repos\Test\Test\Test.cpp 49 Активные
Предупреждение C6201 Индекс "1024" находится вне диапазона от "0" до "1023" для буфера "this->files", возможно, размещенного в стеке. Test F:\f_prog\repos\Test\Test\Test.cpp 66 Активные
Предупреждение C26432 Если вы определяете или удаляете какие-либо операции по умолчанию в типе "class gymfile", определите или удалите их все (c.21). Test F:\f_prog\repos\Test\Test\Test.cpp 133 Активные
Предупреждение C26485 Выражение "this->files": не допускайте вырождения массива в указатель (bounds.3). Test F:\f_prog\repos\Test\Test\Test.cpp 69 Активные
Предупреждение C26485 Выражение "this->files": не допускайте вырождения массива в указатель (bounds.3). Test F:\f_prog\repos\Test\Test\Test.cpp 116 Активные
Предупреждение C26485 Выражение "filname": не допускайте вырождения массива в указатель (bounds.3). Test F:\f_prog\repos\Test\Test\Test.cpp 82 Активные
Предупреждение C26485 Выражение "filname": не допускайте вырождения массива в указатель (bounds.3). Test F:\f_prog\repos\Test\Test\Test.cpp 88 Активные
Предупреждение C26485 Выражение "filname": не допускайте вырождения массива в указатель (bounds.3). Test F:\f_prog\repos\Test\Test\Test.cpp 89 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 40 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 44 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 49 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 66 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 97 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 101 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 102 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 105 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 106 Активные
Предупреждение C26482 В качестве индексов массивов используйте только константные выражения (bounds.2). Test F:\f_prog\repos\Test\Test\Test.cpp 107 Активные
Вывод: Использование в С++ функций из C не привело ни к чему хорошему.