текст перекладу
Я пишу цей пост, припускаючи, що кожен, хто його читає, розуміє мову програмування C++.
Короткий огляд вказівників
Вказівники — це просто адреси пам'яті. У сучасних системах це зазвичай віртуальні адреси. Це означає, що вони не вказують безпосередньо на фізичну пам'ять (як RAM), а проходять через процес відображення. Подумайте про віртуальні адреси як про координати на карті, які система транслює в фактичне фізичне місце.
Ось швидка діаграма, яку я створив, щоб пояснити свої думки.
Серіалізація (і десеріалізація)
Серіалізація — це процес перетворення даних у пам'яті в формат, який можна зберігати або передавати, наприклад, рядок або бінарний файл. Це схоже на створення знімка об'єкта або змінної та збереження його для подальшого використання.
Десеріалізація — це зворотний процес. Вона приймає збережений формат (рядок, бінарний тощо) і відновлює оригінальні дані в пам'яті. Це схоже на завантаження вашого знімка назад у використовуючи форму.
Перетворення вказівників у рядки (і назад)
Ми можемо взяти вказівник, перетворити його в рядок (серіалізувати), а потім перетворити його назад у вказівник (десеріалізувати). Ось простий приклад на C++:
Код серіалізації:
#include
#include // Для std::stringstream
#include // Для std::string
std::string serializePointer(int* pointer) {
uintptr_t addressAsInt = reinterpret_cast(pointer);
std::stringstream ss;
ss << std::hex << addressAsInt; // Перетворити в шістнадцятковий формат для зручності
return ss.str();
}
int main() {
// Крок 1: Визначити змінну та отримати її адресу
int myVariable = 42;
int* originalPointer = &myVariable;
// Серіалізувати вказівник
std::string serializedAddress = serializePointer(originalPointer);
std::cout << "Serialized Address: " << serializedAddress << std::endl;
return 0;
}
Код десеріалізації:
#include
#include // Для std::stringstream
#include // Для std::string
int* deserializePointer(const std::string& serializedAddress) {
uintptr_t deserializedInt;
std::stringstream ss(serializedAddress);
ss >> std::hex >> deserializedInt;
return reinterpret_cast(deserializedInt);
}
int main() {
// Імітуємо отримання серіалізованої адреси (замінити на фактичне серіалізоване значення)
std::string serializedAddress = "2c8e3ffca0"; // Приклад значення; замініть на вашу серіалізовану адресу
// Десеріалізувати вказівник
int* deserializedPointer = deserializePointer(serializedAddress);
// Доступ або зміна значення змінної за допомогою десеріалізованого вказівника
std::cout << "Значення myVariable через десеріалізований вказівник: "
<< *deserializedPointer << std::endl;
*deserializedPointer = 99; // Змінити значення через вказівник
std::cout << "Змінене значення myVariable: " << *deserializedPointer << std::endl;
return 0;
}
Передача між процесами
Теоретично ми повинні мати змогу серіалізувати адресу пам'яті, передати її в інший процес за допомогою якогось методу комунікації (наприклад, REST API, сокети або навіть протоколи комунікації між процесами, такі як тунелі) і здійснити десеріалізацію, щоб прочитати дані за цією адресою.
На жаль, це неможливо. Раніше я розповідав, що кожен процес має свою власну таблицю віртуальних адрес, яка відображає реальну фізичну адресу в RAM.
Оскільки кожен процес має свою унікальну таблицю віртуальних адрес пам'яті, адреса, яку ви отримуєте, серіалізуєте та відправляєте з одного процесу, не буде мати таке саме значення у віртуальній адресній таблиці, навіть якщо її можна десеріалізувати.
Перекладено з: In Theory, We Should Be Able To Pass Pointers As Strings?