Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Что записано в памяти перед динамическим массивом?

85K
05 января 2013 года
deviser
10 / / 05.01.2013
Здравствуйте.

 
Код:
int *ptr_int = new int[10];

for (int i=-4; i<=-1; i++)
    cout << *(ptr_int + i) << " ";
Вывод: 40 1 333 -33686019

40 - это размер массива в байтах в Windows.

А что означают остальные числа? Может это просто мусор и ничего не означают?
412
07 января 2013 года
grgdvo
323 / / 04.07.2007
То что вы видите перед массивом, выделенным динамически, является служебной структурой аллокатора динамической памяти. В частности в glibc - это вроде структура malloc_chunk (см. исходники glibc malloc/malloc.c). Однако, размер, записанный в этой структуре - вы его видите - не всегда соответсвует тому количеству байт, которые пытается получить пользователь. Срабатывает выравнивание, еще различные оптимизационные решения.
Поэтом формально, вы правы - там в первых 8-16 байтах не мусор! Он что-то значит для аллокатора, но с точки зрения языка С++ и программы на С++ эта информация - мусор. Является принципиальной ошибкой обращаться за пределы выделенного чанка. Кстати сборка в режиме отладким скорее всего должна выдать какие-нибудь ассерты при обращении таким образом.

Все сказанное относится к Linux. Что в Visual Studio сказать не могу, не уверен, что можно добыть исходники их C/C++ Library. В них наверняка содержится точный ответ.
1
05 января 2013 года
kot_
7.3K / / 20.01.2000
это все мусор. в том числе и "40 - это размер массива в байтах в Windows" Кстати, почему 40 то? :)
85K
05 января 2013 года
deviser
10 / / 05.01.2013
Цитата:
это все мусор.


Я много раз проверял для разных размеров массивов. И всегда в этом месте записывается число, которое показывает его размер. Т.е. по адресу ptr_int - 4.

Цитата:
Кстати, почему 40 то? :)


40 = sizeof(int) * 10. Тут вроде бы все ясно)

1
05 января 2013 года
kot_
7.3K / / 20.01.2000
Цитата: deviser

40 = sizeof(int) * 10. Тут вроде бы все ясно)


угу. зависит от архитектуры. :)
а если так?

 
Код:
char *ptr_int = new char[10];

for (int i=-4; i<=-1; i++)
    cout << (int)*(ptr_int + i) << " ";
вывод:
-127 6 -37 0

"размер" куда вдруг подевался?
85K
05 января 2013 года
deviser
10 / / 05.01.2013
Цитата:
"размер" куда вдруг подевался?


Никуда он не подевался )

 
Код:
char *ptr = new char[10];

for (int i=-4; i<=-1; i++)
    cout << (int)*( (int *)ptr + i ) << " ";
10 1 333 -33686019

Здесь опять видно что в 16 байт от начала массива находится его размер (имею ввиду что int занимает 4 байта)
И что интересно, все цифры те же самые. После размера массива идет единица (что она означает?), дальше 333 (что это число означает?)
412
05 января 2013 года
grgdvo
323 / / 04.07.2007
Какая у вас среда разработки, скажите. Какой компилятор?
Либо вам очень везет, либо у вас какой-то "чудесный" и "удивительный" аллокатор кучи используется.
Вообще-то ответ уже был дан сразу! Там должен быть мусор!
85K
05 января 2013 года
deviser
10 / / 05.01.2013
Цитата:
Какая у вас среда разработки


Visual Studio 2010 Professional

1
05 января 2013 года
kot_
7.3K / / 20.01.2000
Цитата: deviser
Цитата:
Какая у вас среда разработки


Visual Studio 2010 Professional


мне лень ставить студию и проверять на ней - но в любом случае - это мусор.
В указателе не хранится количество элементов массива (по крайней мере в С++), в указателе хранится адрес первого элемента.

360
05 января 2013 года
P*t*
474 / / 15.02.2007
gcc версия 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

Код:
#include <iostream>

using namespace std;

int main() {
    cout << "First" << endl;
    for (int size = 1; size <= 16; ++size) {
        cout << "  size = " << size << " : ";
        int *ptr = new int[size];
        for (int i=-4; i<=-1; i++)
            cout << *( ptr + i ) << " ";
        cout << endl;
    }
    cout << "Second" << endl;
        for (int size = 1; size <= 16; ++size) {
                cout << "  size = " << size << " : ";
                int *ptr = new int[size];
                for (int i=-4; i<=-1; i++)
                        cout << *( ptr + i ) << " ";
                cout << endl;
        }
    return 0;
}
Код:
First
  size = 1 : 0 0 33 0
  size = 2 : 0 0 33 0
  size = 3 : 0 0 33 0
  size = 4 : 0 0 33 0
  size = 5 : 0 0 33 0
  size = 6 : 0 0 33 0
  size = 7 : 0 0 49 0
  size = 8 : 0 0 49 0
  size = 9 : 0 0 49 0
  size = 10 : 0 0 49 0
  size = 11 : 0 0 65 0
  size = 12 : 0 0 65 0
  size = 13 : 0 0 65 0
  size = 14 : 0 0 65 0
  size = 15 : 0 0 81 0
  size = 16 : 0 0 81 0
Second
  size = 1 : 0 0 33 0
  size = 2 : 0 0 33 0
  size = 3 : 0 0 33 0
  size = 4 : 0 0 33 0
  size = 5 : 0 0 33 0
  size = 6 : 0 0 33 0
  size = 7 : 0 0 49 0
  size = 8 : 0 0 49 0
  size = 9 : 0 0 49 0
  size = 10 : 0 0 49 0
  size = 11 : 0 0 65 0
  size = 12 : 0 0 65 0
  size = 13 : 0 0 65 0
  size = 14 : 0 0 65 0
  size = 15 : 0 0 81 0
  size = 16 : 0 0 81 0
Видно, что
1) Соблюдается закономерность - числа зависят только от размера массива. Видимо третье число - размер выделенной памяти +1. Память похоже выделяется только кусками по 16 байт. Также можно предположить, что перед самим массивом имеется 8 (а не 4) байт с доп информацией.
2) Закономерность явно не такая, как написал deviser. Т.е это определенно зависит от компилятора.

P.S У меня ощущение, что сейчас половина форума дружно займется исследованиями мусора.
70K
06 января 2013 года
ProkletyiPirat
76 / / 25.07.2012
это не мусор!!!!! а служебные данные!
ну во первых точно неизвестно где будут записаны эти служебные данные слева или справа (точно может отличаться, но вот от чего зависит (OS, SW или HW) мне неизвестно)

во вторых то сколько выделено памяти под служебку также отличается (скорее всего из-за х32 и х64)

в третьих что 100% там лежит:
1.сколько байт занимает массив(скорее всего сколько там элементов), для операции deletе [ ]
2.тип хранимой информации, для dynamic_cast, то есть все типы нумеруются (какая то последовательность бит) и при dynamic_cast эти биты сравниваются

в четвёртых положение самих значений отличается у разных типов. например для

 
Код:
class my{
};
первые -4байта от указателя будет размер_массива, А для инта это будут совсем другие байты

согласно всему вышеперечисленному как то работать с этой служебкой невозможно!!!! но именно с ней работает deletе [ ], dynamic_cast и typeid



p.s. когда-то очень сильно удивился так как максимальное число элементов в массиве new это 0х7fffffff (2 147 483 647)




--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
ответы на вопросы:
Цитата: deviser
Цитата:
точно неизвестно где будут записаны эти служебные данные слева или справа


Вы имеете ввиду перед массивом или после него?


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

Цитата: UserNet2008
А если такой, что покажет:
 
Код:
int *massa = new int[10][10];
может измениться 1 на 2


обычный двумерный массив записывается одной линией то есть а[5][5] будет занимать 5+5=10 и идти эти 10 будут подряд
но динамический а[5][5] должен выделиться в виде шести одномерных массивов по 5, один будет связывать адреса (это а[5]), а другой хранить значения (это а[#][5])

85K
06 января 2013 года
deviser
10 / / 05.01.2013
А вот результат в Visual Studio если создание массива засунуть в цикл, как у P*t*:

Код:
int *ptr;

for (int i=1; i<=10; i++)
{
    ptr = new int[i];

    for (int j=-4; j<=-1; j++)
        cout << (int)*((int *)ptr + j) << " ";

    cout << endl;
}
4 1 333 -33686019
8 1 733 -33686019
12 1 738 -33686019
16 1 743 -33686019
20 1 748 -33686019
24 1 753 -33686019
28 1 758 -33686019
32 1 763 -33686019
36 1 768 -33686019
40 1 773 -33686019

(Я тут столбики выровнил)

)
Первое число - это размер массива
Второе и четвертое вообще не меняются
А вот с третьим не совсем понятно. При увеличении размера массива это число тоже увеличивается.))

Только что заметил. Вообщем числа в третьем столбике увеличиваются на 5
85K
06 января 2013 года
deviser
10 / / 05.01.2013
Цитата:
точно неизвестно где будут записаны эти служебные данные слева или справа


Вы имеете ввиду перед массивом или после него?

327
06 января 2013 года
UserNet2008
748 / / 03.04.2010
А если такой, что покажет:
 
Код:
int *massa = new int[10][10];
может измениться 1 на 2
277
06 января 2013 года
arrjj
1.7K / / 26.01.2011
Ну естественно гдето храниться такая инфа должна, иначе бы простой код типа
 
Код:
int *a = new int[10];
char * b=(char*)a;
delete [] a;
не мог бы корректно освободить память

а вот где она хранится (непосредственно перед массивом или гдето в специальном месте) зависит от компилятора
85K
06 января 2013 года
deviser
10 / / 05.01.2013
Подскажите как все то же самое сделать для двумерного массива. Вот таким способом пытаюсь

Код:
int **ptr;

for (int i=1; i<=10; i++)
{
    ptr = new int*[i];

    for (int j=-4; j<=-1; j++)
        cout << *(ptr + i) << " ";

    cout << endl;
}
Но выводит какие то адреса!
85K
06 января 2013 года
deviser
10 / / 05.01.2013
Все, сам сделал

Код:
int **ptr;

for (int i=1; i<=10; i++)
{
    ptr = new int*[i];

    for (int j=-4; j<=-1; j++)
        cout << (int)*(ptr + j) << " ";

    cout << endl;
}
Результат тот же самый. Никаких изменений
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог