K
K
kos_dev2021-12-21 08:50:59
C++ / C#
kos_dev, 2021-12-21 08:50:59

How to fix AccessViolation when reading a pointer read with CArchive?

There are two projects: DLL MFC to designate the functionality and .NET's to read the functionality of the library.
Almost all functions defined in the library work, except for one that reads objects from a file using CArchive (these objects were previously written to the file, no errors occurred, the serialization method is defined, DECLATE / IMPLEMENT is defined, there is an empty constructor)

Function declarations in C#
[DllImport("testlib.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void ReadFromFile([MarshalAs(UnmanagedType.LPStr)] string path);


Implementing a method in C++ that throws an exception
std::vector<Fruit*> plate; // Вектор, в котором будем хранить считанные объекты
//....
extern "C" _declspec(dllexport) void __stdcall ReadFromFile(char* path)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  CFile file(CString(path), CFile::modeRead);
  CArchive ar(&file, CArchive::load);
  
  int n;
  ar >> n;
  for (int i = 0; i < n; i++)
  {
    Fruit* fruit;
    ar >> fruit;
    plate.push_back(fruit);
    auto cstrName = fruit->name; // Для наглядности. Именно в этом моменте возникает исключение AccessVIolation
  }

  ar.Close();
  file.Close();
}


If needed - a method for writing a file using CArchive
extern "C" _declspec(dllexport) void __stdcall WriteIntoFile(char* path)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  CFile file(CString(path), CFile::modeCreate | CFile::modeWrite);
  CArchive ar(&file, CArchive::store);
  
  ar << plate.size();
  for (auto o : plate)
  {
    ar << o;
  }

  ar.Close();
  file.Close();
}


Just in case, the Fruit.cpp class implementation and Fruit.h header file

fruit.h
#ifndef FRUIT_H
#define FRUIT_H
#include "pch.h"

class Fruit : public CObject
{
  DECLARE_SERIAL(Fruit);
public:

  CString name;

  Fruit();
  Fruit(CString cname);
  ~Fruit();

  virtual void Serialize(CArchive& ar);
};

#endif

fruit.cpp
#include "pch.h"
#include "Fruit.h"

IMPLEMENT_SERIAL(Fruit, CObject, 1);
void Fruit::Serialize(CArchive& ar)
{
  CObject::Serialize(ar);
  if (ar.IsStoring())
  {
    ar << name;
  }
  else
  {
    ar >> name;
  }
}

Fruit::Fruit(CString cname)
{
  name = cname;
}

Fruit::Fruit() {}
Fruit::~Fruit() {}



As I understand it, it is not possible to write the object received by CArchive into the Fruit* pointer normally.
Please tell me how to fix this.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
K
kos_dev, 2021-12-24
@kos_dev

Whether it is not enough someone the decision of a similar problem is required.
The bottom line is that at first CArchive writes the size of the collection when writing, and then the collection itself. And when reading from a file, we use CArchive to first read the size of the collection, which is in the file, and then each object.
So, the error was quite simple - we wrote down the size as vectorObject.size() - which returns a size_t object with a size of 8 bytes, and read the size into an INT, the size of which is 4 bytes, thereby continuing to read objects from the file - NULL objects were generated.
To solve it, it is enough to either write the size as (INT) vectorObject.size() and read the size also in INT.
Either write vectorObject.size() -> size_t value, and read accordingly too:
size_t count;
ar >> count;

R
res2001, 2021-12-21
@res2001

I don’t know what is in CArchive and in general I haven’t picked up MFC for a long time, but I assume that you need to use this option:

Fruit fruit;
ar >> fruit;

For serialization / deserialization, the Serialize method of your own class is called, i.e. CArchive itself does not create serializable classes. Therefore, you must pass operations >> a reference to an existing class, not a pointer. ar will simply overwrite the contents of the class, or rather not overwrite ar, but your Serialize method.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question