Вопрос стекового фрейма: Java против C ++ - PullRequest
7 голосов
/ 26 августа 2009

Q1. В Java все объекты, массивы и переменные класса хранятся в куче? То же самое верно для C ++? Является ли сегмент данных частью кучи?

А как насчет следующего кода на C ++?

class MyClass{
    private:
            static int counter; 
            static int number;
};

MyClass::number = 100;

Q2. Насколько я понимаю, переменные, которым компилятору присваивается определенное значение, хранятся в сегменте данных, а неинициализированные глобальные и статические переменные хранятся в BSS (блок начинается с символа). В этом случае MyClass :: counter, являющийся статическим, инициализируется компилятором в ноль, поэтому он сохраняется в BSS, а MyClass :: number, который инициализируется равным 100, сохраняется в сегменте данных. Правильно ли я делаю заключение?

Q3. Рассмотрим следующий фрагмент кода:

void doHello(MyClass &localObj){   
// 3.1 localObj is a reference parameter, where will this get stored in Heap or Stack?
      // do something
}

void doHelloAgain(MyClass localObj){   
// 3.2 localObj is a parameter, where will this get stored in Heap or Stack?
      // do something
}

int main(){
      MyClass *a = new MyClass();  // stored in heap

      MyClass localObj;   
      // 3.3 Where is this stored in heap or stack?
      doHello(localObj);
      doHelloAgain(localObj);
}

Надеюсь, я разъяснил свои вопросы всем

EDIT:

Пожалуйста, ознакомьтесь с статьей для понимания BSS

EDIT1: Изменено имя класса с MyInstance на MyClass, так как оно было плохим именем. Искренние извинения

EDIT2: Изменен номер переменной члена класса с нестатического на статический

Ответы [ 5 ]

6 голосов
/ 26 августа 2009

Это несколько упрощенно, но, насколько мне известно, в большинстве случаев оно точное.

В Java все объекты размещаются в куче (включая все ваши переменные-члены). Большинство других вещей (параметров) являются ссылками, а сами ссылки хранятся в стеке вместе с нативными типами (целыми числами, longs и т. Д.), За исключением строки, которая является скорее объектом, чем нативным типом.

В C ++, если бы вы выделяли все объекты с помощью ключевого слова "new", это было бы в значительной степени аналогично java, но в C ++ есть один уникальный случай, потому что вы можете вместо этого размещать объекты в стеке не всегда нужно использовать «новый»).

Также обратите внимание, что производительность кучи Java ближе к производительности стека C, чем производительность кучи C, сборщик мусора делает некоторые довольно умные вещи. Это все еще не так хорошо, как стек, но намного лучше, чем куча. Это необходимо, поскольку Java не может размещать объекты в стеке.

2 голосов
/ 26 августа 2009

Q1

Java также хранит переменные в стеке, но экземпляры классов размещаются в куче. В C ++ вы можете свободно размещать экземпляры классов либо в стеке, либо в куче. Используя ключевое слово new, вы выделяете экземпляр в куче.

Сегмент данных не является частью кучи, но выделяется при запуске процесса. Куча используется для динамического выделения памяти, когда сегмент данных статичен, а содержимое известно во время компиляции.

Сегмент BSS - это просто оптимизация, когда все данные, принадлежащие сегменту данных (например, строка, постоянные числа и т. Д.), Которые не инициализированы или инициализированы нулем, перемещаются в сегмент BSS. Сегмент данных должен быть встроен в исполняемый файл, и, перемещая «все нули» до конца, они могут быть удалены из исполняемого файла. Когда исполняемый файл загружен, сегмент BSS выделяется и инициализируется нулем, и компилятор все еще может знать адреса различных буферов, переменных и т. Д. Внутри сегмента BSS.

Q2

MyClass::number хранится там, где размещен экземпляр класса MyClass. Это может быть либо в куче, либо в стеке. Обратите внимание, что в Q3 a указывает на экземпляр MyClass, выделенный в куче, в то время как localObj выделяется в стеке. Таким образом, a->number находится в куче, а localObj.number находится в стеке.

Поскольку MyClass::number является переменной экземпляра, вы не можете назначить ее следующим образом:

MyClass::number = 100;

Однако вы можете назначить MyClass::counter как статическое (за исключением того, что оно является приватным):

MyClass::counter = 100;

Q3

При вызове doHello переменная localObjmain) передается по ссылке. Переменная localObj в doHello ссылается на эту переменную в стеке. Если вы измените его, изменения будут сохранены в стеке, где выделено localObj в main.

Когда вы вызываете doHelloAgain, переменная localObjmain) копируется в стек. Внутри doHelloAgain переменная localObj размещается в стеке и существует только на время вызова.

1 голос
/ 26 августа 2009

Все области памяти в C ++ перечислены здесь

1 голос
/ 26 августа 2009

В C ++ объекты могут быть размещены в стеке ... например, localObj в основной подпрограмме Q3.

Я чувствую некоторую путаницу между классами и экземплярами. «MyInstance» имеет больше смысла как имя переменной, чем имя класса. В вашем примере Q1 «число» присутствует в каждом объекте типа MyInstance. "counter" является общим для всех экземпляров. «MyInstance :: counter = 100» является допустимым назначением, а «MyInstance :: number = 100» - нет, поскольку вы не указали для какого объекта должен быть назначен член "number".

1 голос
/ 26 августа 2009

Q1. В Java все объекты, массивы и переменные класса хранятся на кучи? То же самое верно для C ++? Является сегмент данных часть кучи?

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

Единственные объекты времени находятся в куче, если вы используете ключевое слово new или что-то из семейства функций malloc.

Q2. Насколько я понимаю, переменные, которые задаются конкретным значение компилятором хранятся в данных сегмент, и неинициализированный глобальный и статические переменные хранятся в BSS (Блок начинается с символа). В этом case, MyInstance :: counter является статическим инициализируется компилятором в ноль и поэтому он хранится в BSS и MyInstance :: число, которое инициализируется до 100 хранится в сегмент данных. Правильно ли я делаю заключение?

Да, вы правильно понимаете раздел BSS. Однако, поскольку number не является статичным, код:

MyInstance::number = 100;

недопустимо, его нужно сделать статическим или правильно инициализировать в конструкторе. Если вы инициализируете его в конструкторе, он будет существовать везде, где размещен владеющий объект. Если вы сделаете это статическим, он окажется в разделе данных ... если где-нибудь. Часто static const int переменные могут быть встроены непосредственно в используемый код, так что глобальная переменная вообще не нужна.

Q3. Рассмотрим следующий фрагмент кода: ...

void doHello(MyInstance &localObj){

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

void doHelloAgain(MyInstance localObj){

a копия переданного параметра помещается в стек.

MyInstance localObj;
// 3.3 Where is this stored in heap or stack?

localObj находится в стеке.

...