Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопросы по массиву байт, Операции над таким массивом 
:(
    Опции темы
EgoBrain
Дата 29.5.2013, 07:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Код

BYTE* memory_chunk = new BYTE[10];
BYTE* ptr = &memory_chunk[0];


1). Как я понимаю байты выделились в куче, значит эту память можно освободить, как это сделать?
Операции delete и delete[] крашат программу.

2). Если после арифметических операций над указателем memory_chunk я переместился в конец массива, как вернуться в начало?
Предположил что возможно
Код

memory_chunk = &memory_chunk[0];

казалось бы всё логично и просто - взять адрес на первый байт куска памяти, как и в случае с переменной ptr. Но почему то не срабатывает, то есть memory_chunk ничего в стандартный поток (непонятно куда теперь указывает).
В то же время если memory_chunk-у присвоить значение ptr-а, то всё в порядке, и даже если не трогать memory_chunk указатель и перемещаться по памяти через ptr,а потом взять и еще раз ptr = &memory_chunk, то тоже все в проядке. Вобщем задача решается через использование дополнительной переменной, но можно же обойтись и одной поидее.

3). Как вывести адрес байта?

Хотел провести элементарный эксперемент с освобождением памяти и столкнулся с кучей вопросов  smile 

Это сообщение отредактировал(а) EgoBrain - 29.5.2013, 08:47
PM MAIL ICQ Skype   Вверх
Guinness
Дата 29.5.2013, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 21.6.2009
Где: Зеленоград

Репутация: 2
Всего: 10



1). В смысле выделить 10 байт и из них удалить 5? Если не ошибаюсь так делать нельзя.
2). Пример работы с указателями в посте bsa. Лично я не знаю способов без ввода ptr-а. Либо постоянно работать относительно memory_chunk, т.е. никогда не смещать указатель с начала выделенной памяти и прибавлять нужное Вам смещение. Либо запоминать смещение указателя относительно начала выделенной памяти.
3). 
Код

#include <cstdio>
#include <iostream>
#include <iomanip>

int main()
{
    using std::cout;
    using std::hex;
    using std::endl;

    char *ch_ptr = new char[10];

    cout << hex << ch_ptr << endl;
    cout << hex << (ch_ptr+1) << endl;

    printf("0x%x\n", ch_ptr);
    printf("0x%x\n", ch_ptr+1);
}

Забавно, через cout не получилось) Видимо я делаю что-то не так.
PM MAIL   Вверх
EgoBrain
Дата 29.5.2013, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Спасибо за напоминание про printf, я его не использую поэтому сразу не подумал smile
Спомощью него выяснилось, что судя по всему операция индексации ptr[i] скорее всего тоже самое что и ptr + i, то есть отностильено текущей позиции в массиве. Причем i может принимать отрицательные значения (сюрприз)  smile 
Код

BYTE* memory_chunk = new BYTE[10];
BYTE* ptr = &memory_chunk[0];
    
while(*memory_chunk != '\0')
{
    *memory_chunk = 1;
    memory_chunk++;
}

memory_chunk = &memory_chunk[0]; //--memory_chunk[0] указывает на memory_chunk + 0 (на терминатор строки)--
cout<<"memory_chunk = '"<<memory_chunk<<"'"<<endl<<"ptr = '"<<ptr<<"'"<<endl;

ptr содержит адрес первого байта куска памяти (то что нужно).

Только сейчас обратил внимание, почему 24 смайла а не 10?
PM MAIL ICQ Skype   Вверх
Guinness
Дата 29.5.2013, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 21.6.2009
Где: Зеленоград

Репутация: 2
Всего: 10



Цитата(EgoBrain @  29.5.2013,  10:04 Найти цитируемый пост)
Спомощью него выяснилось, что судя по всему операция индексации ptr[i] скорее всего тоже самое что и ptr + i, то есть отностильено текущей позиции в массиве.

В моем предыдущем посте я ссылочку кинул на пост, где это все расписывается)

Цитата(EgoBrain @  29.5.2013,  10:04 Найти цитируемый пост)
Только сейчас обратил внимание, почему 24 смайла а не 10?

Т.е. почему цикл прошёл 24 раза, а не 10? У Вас неинициализированный массив, количество прохождения цикла может варьироваться, т.к нулевой байт может встретить как внутри массива, так и далеко вне его.
PM MAIL   Вверх
EgoBrain
Дата 29.5.2013, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Цикл то может и прошел N раз (выполнений программы было множество, стабильно 24 смайла записывается) это ладно, почему кусок больше выделенного размера?

Цитата(Guinness @  29.5.2013,  09:32 Найти цитируемый пост)
В моем предыдущем посте я ссылочку кинул на пост, где это все расписывается)

Я эту тему видел, и пост bsa соответсвенно тоже, но извините, где там говорится, что индексация указателя ведется относительно текущего его "положения"?

З.Ы. Касательно вопроса №1, программа крашилась видимо изза этого неправильного цикла..
PM MAIL ICQ Skype   Вверх
Guinness
Дата 29.5.2013, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 21.6.2009
Где: Зеленоград

Репутация: 2
Всего: 10



Цитата(EgoBrain @  29.5.2013,  10:44 Найти цитируемый пост)
Я эту тему видел, и пост bsa соответсвенно тоже, но извините, где там говорится, что индексация указателя ведется относительно текущего его "положения"?

Ну, если Вы внимательно читали, то заметили бы следующее:
Код

int *p0 = array;
p0[3] = 0;
p0 += 3;
*p0 = 0;
int *p1 = array[1];
*(p1+2) = 0;

Цитата(bsa @  23.5.2013,  22:52 Найти цитируемый пост)
Эти все операции выполняют одно и тоже - делают элемент под номером 3 (считая от 0) равным 0.

Вроде как, это и есть ответ на Ваш вопрос касательно того, как работают указатели.
Цитата(EgoBrain @  29.5.2013,  10:44 Найти цитируемый пост)
Цикл то может и прошел N раз (выполнений программы было множество, стабильно 24 смайла записывается) это ладно, почему кусок больше выделенного размера?

Это же массив С, Вам никто не запрещает выйти за его пределы. Это уже на Вашей совести. Просто 24 байт от начала массива у Вас равен 0.
PM MAIL   Вверх
EgoBrain
Дата 30.5.2013, 01:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Цитата(Guinness @  29.5.2013,  10:07 Найти цитируемый пост)

Это же массив С, Вам никто не запрещает выйти за его пределы. Это уже на Вашей совести. Просто 24 байт от начала массива у Вас равен 0. 

Ладно я условие цикла неверно задал и не проконтролировал выход за пределы (что еще не факт), почему cout выводит 24 байта через ptr, ведь ptr я не трогаю, он содержит правильный адрес..
З.Ы. И всё же - как вернуть ОС эти взятые в долг 10 байт?
PM MAIL ICQ Skype   Вверх
feodorv
Дата 30.5.2013, 04:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Guinness @  29.5.2013,  09:35 Найти цитируемый пост)
Забавно, через cout не получилось)

void * должно помочь:
Код

#include <cstdio>
#include <iostream>
#include <iomanip>

int main()
{
    using std::cout;
    using std::hex;
    using std::endl;
    char *ch_ptr = new char[10];
    cout << (void *) ch_ptr << endl;
    cout << (void *) (ch_ptr+1) << endl;
    printf("0x%x\n", ch_ptr);
    printf("0x%x\n", ch_ptr+1);
}



Цитата(EgoBrain @  30.5.2013,  02:51 Найти цитируемый пост)
З.Ы. И всё же - как вернуть ОС эти взятые в долг 10 байт? 

Конечно, как-то нужно сохранять первоначальный указатель на выделенную память с тем, чтобы его отдать оператору delete:
Код

BYTE* memory_chunk = new BYTE[10];
BYTE* ptr = &memory_chunk[0];
  
for( int i = 0; i < 10-1; i++) 
{
    *ptr = 1;
    ptr++;
}
*ptr = '\0';

...

delete [] memory_chunk;


Добавлено @ 04:46
Цитата(EgoBrain @  30.5.2013,  02:51 Найти цитируемый пост)
что еще не факт

Факт!!! smile 

Это сообщение отредактировал(а) feodorv - 30.5.2013, 04:49


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
EgoBrain
Дата 30.5.2013, 07:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Ок, спасибо участникам: я неправильно заполнил свой массив, поэтому не смог его удалить. Остались вопросы касательно адресного пространства программы smile
1). За его пределы выйти я не могу, тогда какие данные я перезаписал, почему это не повредило программу, она продолжила работать? 
2). Как работает с памятью delete? Почему он пытается освободить не выделенные 10, а все ячейки, которые я трогал?
3). В правильном коде delete сработал, но с данным по тому же адресу все равно можно работать, как минимум читать, значит эта память все равно осталась у приложения?
PM MAIL ICQ Skype   Вверх
Dem_max
Дата 30.5.2013, 08:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 4
Всего: 39



Цитата

1). За его пределы выйти я не могу, тогда какие данные я перезаписал, почему это не повредило программу, она продолжила работать? 

Потому что за пределами массива ничего не было. А если бы было то получил бы AV

 
Цитата

2). Как работает с памятью delete? Почему он пытается освободить не выделенные 10, а все ячейки, которые я трогал?


Пытается все 10, что указано в таблице указателя.
delete - удаляет объект (new Object)
delete[] - удаляет массив объектов (new Object[10])

Цитата

3). В правильном коде delete сработал, но с данным по тому же адресу все равно можно работать, как минимум читать, значит эта память все равно осталась у приложения?

Да память удалилась, но она осталась, и скорее всего останется жить до конца программы или когда менеджер памяти ее не освободит для другого выделения, и повторный доступ не приведет к AV


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
EgoBrain
Дата 30.5.2013, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



Dem_max, извини, но твои ответы еще кривей чем мои вопросы.
Что значит 
Цитата
Потому что за пределами массива ничего не было
, там есть какие-то данные я их вижу в символьном представлении, и эти данные в адресном пространсве моей программы, хотелось бы значть приблизительно что это может быть..


Цитата(Dem_max @  30.5.2013,  08:41 Найти цитируемый пост)
Пытается все 10, что указано в таблице указателя.

Если она пытается удалить только 10, почему тогда delete крашит программу в этом случае?
Код

char* memory_chunk = new char[10];
char* ptr = &memory_chunk[0];
    
while(*ptr != '\0')
{
    *ptr = 1;
    ptr++;
}    

delete[] memory_chunk;

Что там не так становится с памятью? (указатель memory_chunk яж не трогаю)

Самое кривое изложение оказалось самым понятным объяснением
Цитата
Да память удалилась, но она осталась, и скорее всего останется жить до конца программы или когда менеджер памяти ее не освободит для другого выделения, и повторный доступ не приведет к AV 

То есть менеджер выводит память из области приложения только тогда когда он этот кусок не решит отдать чем-то другому, поэтому кусок доступен до поры до времени?
PM MAIL ICQ Skype   Вверх
xvr
Дата 30.5.2013, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Когда вы делаете new [], то менеджер памяти берет кусок свободной памяти и возвращает его вам. Но кроме этого, он (new) заказывает немного больше памяти, чем просили. И в этой дополнительной памяти он располагает информацию для менеджера памяти (в частности для того, что бы потом мог отработать delete). В частности он сохраняет размер куска памяти, ну и возможно еще что то. Все это обычно располагается непосредственно перед возвращенным вам куском памяти.
Когда вызывается delete, он читает инфо перед областью памяти, после чего просто добавляет весь кусок в список свободной памяти, что бы в дальнейшем new смог его снова вернуть.

Отсюда и следуют ответы на все ваши вопросы -

Цитата(EgoBrain @  30.5.2013,  07:10 Найти цитируемый пост)
1). За его пределы выйти я не могу, тогда какие данные я перезаписал, почему это не повредило программу, она продолжила работать? 

За пределами области памяти, которую вам вернули, находится свободная память. Ее вернет следующий new. Вы ее потерли, но так как память там физически есть, то сам факт записи ничего не сломал. А вот структуры менеджера памяти вы поломать могли, т.к. там вполне мог оказаться элемент списка свободной памяти. Но это вы узнаете на следующем new или delete  smile 

Цитата(EgoBrain @  30.5.2013,  07:10 Найти цитируемый пост)
2). Как работает с памятью delete? Почему он пытается освободить не выделенные 10, а все ячейки, которые я трогал?

Он вернул именно 10, так как столько и было записанно в служебной информации. Но вы могли разрушить структуры данных менеджера памяти, когда писали за пределы выделенной вам памяти. Так что последствия delete здесь непредсказуемы

Цитата(EgoBrain @  30.5.2013,  07:10 Найти цитируемый пост)
3). В правильном коде delete сработал, но с данным по тому же адресу все равно можно работать, как минимум читать, значит эта память все равно осталась у приложения? 

А куда она денется? Минимальный квант памяти, которая физически может быть выделена или отнята у приложения - 1 страница. На x86 архитектуре - это 4К памяти. Реально удалить 10 байт памяти процессор не умеет физически.

PM MAIL   Вверх
Guinness
Дата 30.5.2013, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 21.6.2009
Где: Зеленоград

Репутация: 2
Всего: 10



Цитата(EgoBrain @  30.5.2013,  10:45 Найти цитируемый пост)
То есть менеджер выводит память из области приложения только тогда когда он этот кусок не решит отдать чем-то другому, поэтому кусок доступен до поры до времени?

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

Цитата(EgoBrain @  30.5.2013,  10:45 Найти цитируемый пост)
 там есть какие-то данные я их вижу в символьном представлении, и эти данные в адресном пространсве моей программы, хотелось бы значть приблизительно что это может быть..

Там может быть все что угодно. Программа не крашилась, когда Вы туда записывали эти данные, только потому что она слишком простая.
Что интересно, когда я тестировал такие выделения памяти, то заметил:
Код

char cptr[10];
char ch1;
char ch2;

Выделение памяти для одинаковых типов происходит в соседних областях. Т.е. указатель (cptr+10) у меня указывал на область памяти, где хранится ch1. Возможно, это особенности ubuntu + gcc. Не знаю).
Код

    using std::cout;
    using std::hex;
    using std::endl;

    char *ch_ptr = new char[10];
    char *ptr = ch_ptr;

    for(int i = 0; i < 24; ++i){
        *ptr = 1;
        ++ptr;
    }

    delete[] ch_ptr;

При вызове delete[] мне пришел сигнал 
Код

HEAP[console.exe]: 
Heap block at 00032D38 modified at 00032D4A past requested size of a

Цитата(feodorv @  30.5.2013,  05:45 Найти цитируемый пост)
void * должно помочь:

Спасибо, помогло.

Это сообщение отредактировал(а) Guinness - 30.5.2013, 10:25
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.2174 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.