Как я могу сохранить значение в определенном месте в памяти?

Может быть, это простой вопрос вопрос, но я действительно хотел бы знать это наверняка.

Если я хочу сохранить значение, скажем, int, по определенному адресу в памяти (в куче), как мне это сделать?

Скажем, я хочу сохранить значение int 10 по адресу 0x16. Думаю, это можно сделать, вызвав new или malloc: int *p=new int(10); а затем я хочу установить адрес сохраненного значения на 0x16. Сначала я подумал что-то вроде &p=0x16, но это не работает. Мне нужно сделать это, чтобы сохранить некоторую дополнительную информацию перед определенным значением в памяти (которое ранее было выделено пространством памяти с помощью malloc или new).

Я использую Linux и C++ (но C тоже подойдет).

Чего я хочу добиться, так это: один процесс вызывает malloc с размером x, и я хочу сохранить определенное значение (размер) перед выделенной памятью, чтобы я мог получить доступ к размеру позже (когда вызывается free). Поскольку был вызван malloc, я знаю указатель, в котором ОС выделила место для значения, и я просто хочу сохранить размер назначенной памяти в 4 байтах перед назначенной памятью. Что я делаю (в хуке malloc, который я написал), так это выделяю больше памяти (внутренним вызовом mallok), но мне также нужно иметь возможность хранить это значение размера в определенном месте.

Я благодарен за всю помощь.


person Bree    schedule 12.07.2011    source источник
comment
вам действительно действительно следует прочитать несколько руководств по указателям   -  person Karoly Horvath    schedule 12.07.2011
comment
Хотите, чтобы вы хотели сделать, это не законно. Если вы не понимаете ОС и распределитель памяти (что, очевидно, вы не понимаете), тогда он просто выйдет из строя или сделает что-то еще неожиданное. Расскажите нам, чего вы на самом деле пытаетесь достичь, а не того, что, по вашему мнению, вам нужно сделать.   -  person Martin York    schedule 12.07.2011


Ответы (4)


Вы можете сделать это следующим образом:

*(int *)0x16 = 10;  // store int value 10 at address 0x16

Обратите внимание, что предполагается, что адрес 0x16 доступен для записи — в большинстве случаев это приведет к возникновению исключения.

Как правило, вы будете делать такие вещи только для встроенного кода и т. д., где нет ОС, и вам нужно записывать в определенные области памяти, такие как регистры, порты ввода-вывода или специальные типы памяти (например, NVRAM).

Вы можете определить эти специальные адреса примерно так:

volatile uint8_t * const REG_1 = (uint8_t *) 0x1000;
volatile uint8_t * const REG_2 = (uint8_t *) 0x1001;
volatile uint8_t * const REG_3 = (uint8_t *) 0x1002;
volatile uint8_t * const REG_4 = (uint8_t *) 0x1003;

Затем в вашем коде вы можете прочитать регистры записи следующим образом:

uint8_t reg1_val = *REG_1; // read value from register 1
*REG_2 = 0xff;             // write 0xff to register 2
person Paul R    schedule 12.07.2011
comment
Я бы использовал здесь reinterpret_cast, а не приведение в стиле C. Скорее стоит обратить внимание на низкоуровневый, машинно-зависимый характер кода. - person James Kanze; 12.07.2011
comment
Это относится к некоторым системам встроенной/прямой памяти (драйверам и т. д.). Но я думаю, что ОП не в такой ситуации - они, похоже, запутались в концепции памяти процесса. Таким образом, я не думаю, что это на самом деле им поможет (в Linux вы вообще не можете этого сделать) - person edA-qa mort-ora-y; 12.07.2011
comment
@edA: возможно, вы правы - вопрос в его первоначальной форме был довольно расплывчатым / запутанным, но ОП, похоже, впоследствии добавил более подробную информацию о том, чего он хочет достичь. Я не уверен, почему мой ответ заслуживает отрицательного голоса? - person Paul R; 12.07.2011
comment
@James: вопрос помечен как C, так и C++, поэтому я предполагаю здесь наименьший общий знаменатель. - person Paul R; 12.07.2011
comment
@ Пол, я не тот, кто проголосовал против. Из полного вопроса я предполагаю, что они просто ищут общую память. - person edA-qa mort-ora-y; 12.07.2011
comment
@Paul R Я пропустил это. Да, если он хочет, чтобы код работал на C, ему лучше избегать reinterpret_cast. - person James Kanze; 12.07.2011
comment
@edA: Я не уверен - из добавленного последнего абзаца звучит так, будто он хочет возиться с внутренними элементами кучи malloc, то есть спрятать значение размера, непосредственно предшествующее блоку malloc? - person Paul R; 12.07.2011
comment
@ Пол, я истолковал это как означающее, что он хочет отслеживать размер своей памяти, чтобы какой-то другой процесс мог его использовать. Я думаю, нам просто придется оставаться в замешательстве. - person edA-qa mort-ora-y; 12.07.2011

Я считаю, что лучший способ достичь вашей цели - реализовать собственный malloc, который выделит еще 4 байта и сохранит размер блока памяти, например:

void* mymalloc(int size)    
{
    char* ptr = malloc(size+sizeof(int));
    memcpy(ptr, &size, sizeof(int));
    return ptr+sizeof(int); 
}
person Oleg    schedule 12.07.2011
comment
@ Бо правда. Это небольшая иллюстрация. Реализация должна быть более сложной - person Oleg; 13.07.2011

Чего я хочу добиться, так это: один процесс вызывает malloc с размером x, и я хочу сохранить определенное значение (размер) перед выделенной памятью, чтобы я мог получить доступ к размеру позже (когда вызывается free). Поскольку был вызван malloc, я знаю указатель, в котором ОС выделила место для значения, и я просто хочу сохранить размер назначенной памяти в 4 байтах перед назначенной памятью.

Это поэтому не сработает. По закону вам разрешено записывать только те адреса памяти, которые были назначены вашими библиотеками. В C это означает malloc и его друзей. В C++ это также означает malloc (хотя в C++ этого следует избегать) и new.

Любая попытка записи в любую память за пределами явного пространства, выделенного этими схемами распределения, приводит к неопределенному поведению. Что обычно означает «плохие вещи могут случиться».

Например, 4 байта перед адресом, возвращаемым malloc, могут быть частью кучи. То есть структуры данных, которые malloc и free используют для выполнения своей работы. Написав им, вы сейчас испортили кучу; каждое выделение или освобождение памяти теперь сопряжено с опасностью и может привести к эффектному провалу.

Или, может быть, 4 байта перед адресом находятся за пределами вашего виртуального адресного пространства. В этом случае ОС быстро убьет вашу программу. Вот что происходит, когда у вас есть «общая ошибка защиты» или «ошибка сегментации». Хорошая новость заключается в том, что обычно это происходит немедленно, поэтому вы можете увидеть в отладчике, где это произошло. В отличие от повреждения кучи, когда вы не можете сказать, что происходит не так, если вы не знаете, как работает ваша куча (или без инструментов отладки кучи).

person Nicol Bolas    schedule 12.07.2011

Вы можете разместить тип в определенном месте памяти в свободном хранилище (или куче), используя Новое место размещения.

person Alok Save    schedule 12.07.2011