2015-08-21 2 views
2

Я хочу написать код C, чтобы увидеть разницу между статическим и динамическим распределением.Код C, показывающий разницу между статическим и динамическим распределением

Это моя идея, но она не работает.

Это просто инициализирует массив размера 10, но присваивает 100 элементов вместо 10. Затем я проинициализировать другой массив, достаточно большой, в надежде заменить 90 элементов не that're части array1[10], то я распечатать 100 элементы array1.

int i;  
int array1[10]; 
int array2[10000]; 

for(i=0;i<100;i++) 
    array1[i] = i; 

for(i=0;i<10000;i++) 
    array2[i] = i+1; 

for(i=0;i<100;i++) 
    { 
    printf("%d \n",array1[i]); 
    } 

То, что я надеюсь получить мусор снаружи, то первые 10 элементов при использовании статического распределения, после этого, я буду использовать таНос и перераспределить, чтобы гарантировать, что 100 элементов будет там правильно. Но, к сожалению, кажется, что память достаточно большая, так что остальные 100 элементов не будут заменены!

Я попытался запустить код на linux и использовать «ulimit», чтобы ограничить размер памяти, но это тоже не сработало.

Любые идеи, пожалуйста?

ответ

1

Когда вы получаете доступ к array1[10] и более высоким значениям индекса, программа будет просто записывать в соседние ячейки памяти, даже если они не «принадлежат» вашему массиву. В какой-то момент вы можете попытаться получить доступ к ячейке памяти, которая запрещена, но пока вы сбрасываете память, которую ОС предоставила вашей программе, это будет работать. Однако результаты будут непредсказуемыми. Возможно, это приведет к повреждению данных, принадлежащих другой переменной в вашей программе, например. Также может случиться так, что значение, которое вы там написали, по-прежнему будет там, когда вы вернетесь, чтобы прочитать его, если никакая другая переменная не была «должным образом назначена» для этой ячейки памяти. (Это похоже на то, что происходит в конкретном случае, который вы опубликовали.)

Все сказанное я не совсем понимаю, как это связано с потенциальными различиями между распределением статической и динамической памяти, поскольку у вас есть только сделать статическое распределение в программе, и вы сознательно ввели ошибку.

+0

«После этого я буду использовать malloc и realloc, чтобы убедиться, что 100 элементов будут там правильно». – LightXXV

+0

@AhmadNourELDeen Я видел линию, которую вы цитировали здесь, но я не мог этого понять. Какой тип вызова malloc даст вам что-то, совместимое с массивами, которые вы показали в вашем примере? Как вы думаете, что произойдет, когда вы вызовете realloc? Это не имеет никакого четкого контекста в приведенном выше примере, и трудно догадаться, что вы имели в виду, поскольку то, что вы показали до сих пор, имеет определенную ошибку, которая не имеет определенного определенного поведения в стандарте. – Brick

+0

@ gnasher729 Спасибо за исправление. – Brick

1

Вы do получить мусор после первых 10 элементов array1. Все данные после элемента 9 не должны считаться выделенными стеком и могут быть записаны в любой момент. Когда программа печатает 100 элементов из array1, вы можете увидеть остатки цикла for, потому что два массива распределены рядом друг с другом и, как правило, не были записаны. Если это было реализовано в более крупной программе, другие массивы могут занимать пространство после этих двух массивов примеров.

+0

Это то, что я уже сказал в вопросе :) ... что мне делать, чтобы ограничить размер памяти или даже заставить второй массив быть после 10-выделенных элементов массива1? – LightXXV

+0

Прямо сейчас у вас есть проблема в вопросе поиска. Когда вы складываете свои кусочки, гораздо лучше убедиться, что каждая из мелких фигур верна, а не начинается с испорченного фундамента и затем охотится за решением. Вы статически объявляете свой массив из 10 элементов, а затем, когда 'i = 10', ваши оставшиеся данные должны идти куда-то еще.Как правило, вы динамически выделяете 10, а затем, когда вы достигнете 10, «realloc» в два раза больше этой суммы и продолжайте ... –

+0

@AhmadNourELDeen Вы уже ограничили массив до 10 элементов. Вы не можете контролировать, где в памяти будут ваши данные, и вам никогда не понадобится. В упрощенном смысле вы можете требовать только случайные разделы памяти, в результате чего они не могут быть перезаписаны другими программами. – dylanweber

4

C на самом деле не делает никаких проверок границ относительно массивов. Это зависит от ОС, чтобы обеспечить доступ к действительной памяти.

Доступ за пределы массива не определено поведение, от c99 draft standard раздела Приложение J.2 J.2 Неопределенное поведение включает в себя точку последующей:

индекс массива выходит за пределы диапазона, даже если объект видимо доступный с индексом (как в выражении lvalue a [1] [7], с учетом объявления int a [4] [5]) (6.5.6).

В этом примере вы объявляете массив на основе стека.Вызов из привязанной линии приведет к получению памяти из уже выделенного пространства стека. В настоящее время неопределенное поведение не в вашу пользу, так как не существует ошибки Seg. Его программист отвечает за обработку граничных условий при написании кода на C/C++.

+4

Я бы сказал, что поведение не в вас. Сбой, за которым следует разработчик, исправляющий код, является наилучшим возможным результатом. – gnasher729

+0

Я знаю это, я не спрашиваю, почему он правильно напечатал 90 элементов: D .... Я просто спрашиваю, что я могу сделать, чтобы показать, что области, выделенные стеком, могут быть перезаписаны. – LightXXV

+0

@AhmadNourELDeen Пожалуйста, посмотрите [Smashing the Stack for fun and profit] (http://www.win.tue.nl/~aeb/linux/hh/phrack/P49-14). –

0

Изменение размера памяти не решит вашу проблему, потому что, когда вы создаете свои два массива, второй должен быть сразу после первый в памяти.

Ваш код должен делать то, что, по вашему мнению, будет, и на моем компьютере. Вот мой вывод: 0 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 ...

В какой ОС вы используете свой код? (Я на Linux 64bit).

В любом случае, как вам сказали, НЕ КОГДА-ЛИБО ЭТОТ В РЕАЛЬНОЙ ПРОГРАММЕ. Запись вне массива - это неопределенное поведение и может привести к сбою вашей программы.

+0

Да, я знаю :) ... это просто для обучения, а не для реальной программы. Но я тоже использую Linux 64bit! возможно, это случайное поведение ... Я попробую еще раз – LightXXV

0

Выписывание границ массива ничего не докажет и не определено корректно. Как правило, нет ничего умного или интересного в вызове неопределенного поведения. Единственное, что вы достигнете, это случайные сбои.

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

#include <stdio.h> 
#include <stdlib.h> 

int main (void) 
{ 
    int stack; 
    static int data = 1; 
    static int bss = 0; 
    int* heap = malloc(sizeof(*heap)); 

    printf("stack: %p\n", (void*)&stack); 
    printf(".data: %p\n", (void*)&data); 
    printf(".bss: %p\n", (void*)&bss); 
    printf(".heap: %p\n", (void*)heap); 
} 

Это должно напечатать 4 своеобразнейше разные адреса (.data и .bss вероятно, близко друг к другу, хотя). Чтобы точно знать, где начинается определенная область памяти, вам нужно либо проверить скрипт компоновщика, либо использовать системный API. И как только вы узнаете смещение и размер области памяти, вы можете определить, сохраняется ли переменная в одном из разных сегментов памяти.

Смежные вопросы