Как я могу сохранить значение в определенном месте в памяти? - PullRequest
9 голосов
/ 12 июля 2011

Может быть, это простой вопрос, но мне бы очень хотелось знать это точно.

Если я хочу сохранить значение, скажем, 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), но мне также нужно иметь возможность хранить значение этого размера в определенном месте.

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

Ответы [ 4 ]

11 голосов
/ 12 июля 2011

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

*(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
8 голосов
/ 12 июля 2011

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

void* mymalloc(int size)    
{
    char* ptr = malloc(size+sizeof(int));
    memcpy(ptr, &size, sizeof(int));
    return ptr+sizeof(int); 
}
2 голосов
/ 12 июля 2011

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

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

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

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

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

0 голосов
/ 12 июля 2011

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

...