Для начала изучим структуру PVar'ов, её можно найти в утекших исходниках SA-MP 0.3d (учитывая темпы
развития стагнации мультиплеера, можно смело предположить, что в последней версии ничего не изменилось).
Собственно, вот сама структура:
https://github.com/Sasuke78200/open-..._var.h#L13-L22
Открыть/закрыть typedef struct PVAR_DATA_t
{
#pragma pack( 1 )
char pVarName[MAX_PVAR_NAME + 1];
BOOL isReadOnly;
uint32_t pVarType;
int intValue;
float floatValue;
char* stringValue;
} PVAR_DATA;
Для тех, кому лень считать: структура занимает 58 байт, т.е. по 58 байт занимает каждый PVar. Для сравнения, обычная переменная в Pawn занимает всего 4 байта.
Выглядит структура довольно "интересно". Свойство isReadOnly позволяет перевести PVar в состояние "только для чтения", но эта возможность нигде не используется (в SA-MP нет PVar'ов, доступных только для чтения).
Кроме того, для хранения данных отведены целых 3 отдельных свойства: одно для целых чисел, другое для вещественных и третье для строк, что довольно странно, поскольку нельзя использовать PVar для одновременного хранения данных разных типов (т.е. нельзя, например, сохранить сразу число и строку).
В том же исходном файле ниже можно найти структуру класса CPlayerVar:
https://github.com/Sasuke78200/open-..._var.h#L24-L52
Открыть/закрыть class CPlayerVar
{
#pragma pack( 1 )
public:
PVAR_DATA pVars[MAX_PVARS];
BOOL isPVarActive[MAX_PVARS];
uint32_t upperIndex;
CPlayerVar();
~CPlayerVar();
int AddVar(char* varName);
int DeleteVar(char* varName);
int SetIntVar(char* varName, int varValue, BOOL readOnly = 0);
int SetStringVar(char* varName, char* varString, BOOL readOnly = 0);
int SetFloatVar(char* varName, float varValue, BOOL readOnly = 0);
int GetIntVar(char* varName);
char* GetStringVar(char* varName);
float GetFloatVar(char* varName);
int GetVarType(char* varName);
char* GetVarNameFromID(int pVarID);
int FindVarID(char* varName);
void UpdateUpperID();
};
Это структура, место для которой выделяется отдельно для каждого игрока при подключении и высвобождается при выходе игрока с сервера.
Объявление MAX_PVARS можно найти в том же файле, оно равно 800 (собственно, уже давно известно, что можно создать до 800 PVar'ов для каждого игрока).
В структуре можно сразу же заметить самое первое свойство:
PVAR_DATA pVars[MAX_PVARS];
Это говорит о том, что под все 800 PVar'ов используется один общий блок памяти на каждого игрока, а значит все утверждения о том, что "PVar можно удалить и он больше не будет занимать место" ошибочны.
Проверим наш вывод. Найдём в файле
class_player_var.cpp все случаи использования функций malloc/calloc/free и операторов new/delete.
Никакие функции для динамического выделения памяти там не используются, а new и delete используются только для резервирования/высвобождения места под строку, сохраняемую с помощью SetPVarString.
Остальное содержимое хранится в одном общем для всех 800 PVar'ов блоке памяти, который остаётся зарезервированным на протяжении всего времени нахождения игрока на сервере. Что и требовалось доказать.