Освободить структуру, используя арифметику указателей и указатель на элемент этой структуры

У меня есть следующая структура в C ++:

struct wrapper
{
// Param constructor
wrapper(unsigned int _id, const char* _string1, unsigned int _year,
unsigned int _value, unsigned int _usage, const char* _string2)
:
id(_id), year(_year), value(_value), usage(_usage)
{
int len = strlen(_string1);
string1 = new char[len + 1]();
strncpy(string1, _string1, len);

len = strlen(_string2);
string2 = new char[len + 1]();
strncpy(string2, _string2, len);
};
// Destructor
~wrapper()
{
if(string1 != NULL)
delete [] string1;
if(string2 != NULL)
delete [] string2;
}

// Elements
unsigned int     id;
unsigned int     year;
unsigned int     value;
unsigned int     usage;
char*            string1;
char*            string2;
};

Допустим, в main.cpp я выделил память для одного объекта этой структуры:

wrapper* testObj = new wrapper(125600, "Hello", 2013, 300, 0, "bye bye");

Могу ли я теперь удалить весь объект, используя арифметику указателей и указатель, который указывает на один из элементов структуры?

Что-то вроде этого :

void*  ptr = &(testObj->string2);

ptr -= 0x14;

delete (wrapper*)ptr;

Я проверил себя и, видимо, это работает, но я не уверен на 100%, что эквивалентно delete testObj,

Благодарю.

0

Решение

Могу ли я теперь удалить весь объект, используя арифметику указателей и указатель, который указывает на один из элементов структуры?

Теоретически да.

Указатель, который вы даете delete должно иметь правильное значение, и на самом деле не имеет значения, получено ли это значение из существующей переменной-указателя или путем «подстройки» таким образом.

Вы также должны учитывать тип указателя; если ничего другого, вы должны бросить char* перед выполнением арифметики, чтобы вы двигались с шагом в один байт. Ваш текущий код не будет компилироваться, потому что ISO C++ forbids incrementing a pointer of type 'void*' (насколько большой void?).

тем не мение, рекомендую не делаю это вообще. Ваш магический номер 0x14 является ненадежным, учитывая выравнивание и заполнение и потенциал вашей структуры, чтобы изменить форму.

Вместо этого сохраните указатель на фактический объект. Также остановитесь со всем ужасным беспорядком памяти, и используйте std::string, В настоящее время отсутствие конструктора копирования представляет собой неприятную ошибку.

1

Другие решения

Технически такой код работал бы (игнорируя тот факт, что wrapper testObj должно быть wrapper* testObj и что смещение не обязательно 0x14например, сборки отладки иногда дополняют структуры, и, возможно, некоторые другие детали, которые я пропустил), но это ужасная, ужасная идея. Я не могу подчеркнуть, насколько это ужасно.

Вместо 0x14 вы могли бы использовать offsetof макро.

Если вам нравится проводить ночи в компании отладчика, не стесняйтесь делать это.

Я предполагаю, что причиной вопроса является явное любопытство о том, возможно ли использовать арифметику указателей для перехода от членов к родителю, а не то, что вы действительно хотели бы сделать это в рабочем коде. Пожалуйста, скажи мне, что я прав.

3

Вы Можно делать подобные вещи с арифметикой указателей. Ли ты должен это совершенно другая история. Рассмотрим этот макрос (я знаю … я знаю …), который даст вам базовый адрес структуры с учетом ее типа, имя члена структуры и указатель на этот член:

#define ADDRESS_FROM_MEMBER(T, member, ptr) reinterpret_cast<T*>( \
reinterpret_cast<unsigned char *>(ptr) - (ptrdiff_t)(&(reinterpret_cast<T*>(0))->member))
0
По вопросам рекламы [email protected]