crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в копирование и память
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
Алексей1153 Дата 23.12.2011, 14:36
  rp80,


class A
{
    public:
    int ar[3];
    std::vector<int> pi;
    std::string str;
};

A a1,a2;

a1=a2 //корректно
BRE Дата 23.12.2011, 10:56
 
Цитата(rp80 @ 23.12.2011, 11:39) *
Т.е. скопировался как надо только указатель на динамически выделенную память.

Кому надо? Компилятор сделал то что ты ему сказал.
Сделал бинарную копию a2 равную a1 (потеряв при этом указатель на область памяти pi - утечка).
Указатель a2.str как показывал "в никуда", так и показывает - отсюда вылет программы.
Все ожидаемо.


Цитата(rp80 @ 23.12.2011, 11:47) *
И если мы потом поменяем значение по одному указателю, должно поменяться и второе

Так и есть. Там где ты меняешь что-то по указателю, там и меняется (a1.pi[ 0 ] и a2.pi[ 0 ] ).
rp80 Дата 23.12.2011, 10:47
 
Цитата(Алексей1153 @ 23.12.2011, 11:41) *
rp80, как разберёшься с указателями на массивы, открой для себя std-контейнеры )

а в данном случае тебе нужно переопределить оператор присваивания (и конструктор по умолчанию) для корректного копирования

Так в том то и дело, что по идее копирование по умолчанию должно копировать почленно. И если мы потом поменяем значение по одному указателю, должно поменяться и второе
Алексей1153 Дата 23.12.2011, 10:41
  rp80, как разберёшься с указателями на массивы, открой для себя std-контейнеры )

а в данном случае тебе нужно переопределить оператор присваивания (и конструктор по умолчанию) для корректного копирования
rp80 Дата 23.12.2011, 10:39
 
Цитата(Iron Bug @ 23.12.2011, 10:55) *
я в юзерских программах не парюсь и использую кучу. ибо она практически не ограничена и чаще всего скорость доступа совершенно не критична, так как юзерские программы обычно и без того тормозят из-за вывода и экономия на адресах не даёт никакого эффекта.


Я бы тоже не стал лазить в такие дебри. Но стал тут разбираться с копированием объектов и вот такое поведение непонятно.
class A
{
    public:
    int ar[3];
    int* pi;
    char* str;
    A(){ar[0]=ar[1]=ar[2]=0;pi=new int[3];}
};

int main()
{
    A a1,a2;
    a2=a1;
    a1.ar[0]=98;
    a1.pi[0]=123;
    a1.str="zxcf";
    std::cout<<a2.ar[0]<<"\n"<<a2.pi[0]<<"\n"<<a2.str<<std::endl;
}

Выводит: 0 - 123 - Segmentation fault.
Т.е. скопировался как надо только указатель на динамически выделенную память.
BRE Дата 23.12.2011, 10:23
 
Цитата(Iron Bug @ 23.12.2011, 10:55) *
а, ну да. тут ещё оттуда придётся тащить данные. у дров есть функция взятия физического адреса, а вот в юзерспейсе я чота не помню, есть такая фича или нет...

Userspace вообще ничего не знает про физические адреса - он живет в виртуальном адресном пространстве.
Iron Bug Дата 23.12.2011, 9:55
 
Цитата(BRE @ 23.12.2011, 12:17) *
(в сегментных регистрах храняться уже не адреса, а дескрипторы сегментов из специальных дескрипторных таблицах GDT или LDT

а, ну да. тут ещё оттуда придётся тащить данные. у дров есть функция взятия физического адреса, а вот в юзерспейсе я чота не помню, есть такая фича или нет... я-то живу в основном в кернеле :) а для 64 бит GDT чистая абстракция - там один хрен всё линейно.
в общем, тогда лучше не пытаться гадать, а взять какой-нить стандарт ELF или вендозные спецификации и почитать про конкретные оси и конкретные компиляторы. впрочем, от этого разницы никакой не будет. для программиста интерес представляет размер стека, оптимизация работы с указателями и решение использования стека или кучи. я в юзерских программах не парюсь и использую кучу. ибо она практически не ограничена и чаще всего скорость доступа совершенно не критична, так как юзерские программы обычно и без того тормозят из-за вывода и экономия на адресах не даёт никакого эффекта.
Алексей1153 Дата 23.12.2011, 9:49
  rp80, значит компилятор разместил переменную не так, как я подумал ) Но это неважно, суть ты понял, я полагаю
rp80 Дата 23.12.2011, 9:46
 
Цитата(Алексей1153 @ 23.12.2011, 8:33) *
rp80, стек то никуда не девается. А то, что ты правильно выводишь якобы - это уже мусор, одна ко по чистой случайности этот мусор пока ещё соответствует тому, что в него поместили внутри вложенного блока

попробуй вот так

int main()
{
    int* pi;
    {
        int ar[1000000];
        ar[3]=std::rand() % 10 + 1;
        pi=ar;
    }
  
    int ar2[20]={1,2,3,4};
    std::cout<<pi[3];
}


Ничего не меняется, какие переменные потом не определяй, все равно правильно работает )
BRE Дата 23.12.2011, 9:17
 
Цитата(Iron Bug @ 23.12.2011, 8:41) *
если тебя интересует конкретная реализация - ты можешь просто посмотреть адреса в отладчике, и сравнить с регистрами. в архитектуре PC сегмент кода - это то, куда указывает CS. стек - SS. а данные, как правило, помещаются либо в DS, либо в ES (но там могут быть и адреса других сегментов, если идёт обработка константных данных, например). однако, в дебажном варианте распределение немного другое, там есть ловушки для нулевых смещений и выхода за границы массивов, отсутствие оптимизации размещения и всяческие компиляторные вставки для отладки. там может быть немного другое распределение.

Это было актуально во времена ??-DOS работающей в реальном режиме.
Сейчас большинство ОС работает в защищенном режиме (в сегментных регистрах храняться уже не адреса, а дескрипторы сегментов из специальных дескрипторных таблицах GDT или LDT), да и процессы все выполняются в flat-режиме, в котором все сегменты (код, данные, стек) настраиваются на одни и те жи адреса виртуальной памяти.
Защита выполняется на уровне страниц памяти (защита на уровне сегментов не используется вообще - для скорости).
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 29.3.2024, 16:52