Существует ли альтернативный способ освободить динамично выделенную память в C - не использование свободного () функция?

Создайте класс анализатора общего ресурса, который включает в себя необходимые функции:

class ShareAnalyzer {

    private final int[] aktiePris;
    private int sellMinut = 0, buyMinut = 0, buyPrice,  sellPrice;

    ShareAnalyzer(int[] aktiePris) {

        this.aktiePris = aktiePris;
        findProfit();
    }

    private void findProfit() {

        if (aktiePris.length < 1) return ;
        int minValue = aktiePris[0];
        int maxValue = minValue;
        int indeksMaxMinut = 0, indeksMinMinut = 0;

        for (int i = 1; i < aktiePris.length; i++) {
            if (aktiePris[i] > maxValue) {
                maxValue = aktiePris[i];
                indeksMaxMinut = i;
                int priceDiff = maxValue - minValue;
                if (priceDiff > getProfit()) {
                    sellPrice = maxValue;
                    buyPrice  = minValue;
                    sellMinut = indeksMaxMinut;
                    buyMinut = indeksMinMinut;
                }
            } else if (aktiePris[i] < minValue) {
                minValue = maxValue = aktiePris[i];
                indeksMinMinut = i;
            }
        }
    }

    //time in minutes from opening
    int getSellTime() {return sellMinut;}

    int getSellPrice() {return sellPrice;}

    //time in minutes from opening
    int getBuyTime() {return buyMinut;  }

    int getBuyPrice() {return buyPrice;}

    int getProfit() {   return sellPrice - buyPrice;    }
}

Вы также можете добавить метод для распечатки информации об общем анализаторе:

    //this could be implemented as `toString` of ShareAnalyzer
    private static void printShareInfo(ShareAnalyzer shareAnalyzer){
        System.out.println("Best time & price for buying is " + shareAnalyzer.getBuyTime() + " minutes after opening for " + shareAnalyzer.getBuyPrice() + " EUR." + "\n"
                + "Best time & price for selling is " + shareAnalyzer.getSellTime() + " minutes after opening for " + shareAnalyzer.getSellPrice() + " EUR." + "\n"
                + "Profit: " + shareAnalyzer.getProfit());
    }

Создать новый ShareAnalyzer экземпляр для каждой акции, которую вы хотите проанализировать.

public static void main(String args[]) {

    int[] aktiePris1 = new int[]{10, 7, 5, 8, 11, 9};
    ShareAnalyzer shareAnalyzer1 = new ShareAnalyzer(aktiePris1);
    printShareInfo(shareAnalyzer1);

    int[] aktiePris2 = new int[]{2, 12, 4, 7 , 11, 9, 1 , 8};
    ShareAnalyzer shareAnalyzer2 = new ShareAnalyzer(aktiePris2);
    printShareInfo(shareAnalyzer2); 
}

Вы можете запустить код и проверить его, используя эту ссылку

5
задан Bill the Lizard 19 September 2012 в 22:21
поделиться

3 ответа

На самом деле, последний из них эквивалентен вызову free () . Внимательно прочитайте спецификацию realloc () , и вы обнаружите, что он может распределять данные заново или изменять размер выделения (который, особенно если новый размер больше старого, может переместить данные вокруг), и это может освободить память тоже. На самом деле, вам не нужны другие функции; все они могут быть записаны в терминах realloc () . Не то, чтобы кто-то в здравом уме сделал бы это ... но это могло бы быть сделано.

См. Стив Магуайр " Написание твердого кода " для полного анализа опасностей malloc ( ) семейство функций. См. Веб-сайт ACCU для полного анализа опасностей чтения «Написание твердого кода» , Я не уверен, что это так плохо, как об этом говорят обзоры - хотя его полное отсутствие обработки const действительно датирует его (назад к началу 90-х, когда C89 был еще новым и не


D Примечания Макки о MacOS X 10.5 (BSD) интересны ...

Стандарт C99 гласит:

7.20.3.3 Функция malloc

Синопсис

#include <stdlib.h>
void *malloc(size_t size);

Описание

Функция malloc выделяет пространство для объекта, размер которого определяется размером и значение которого не определено.

Возвращает

Функция malloc возвращает либо нулевой указатель, либо указатель на выделенное пространство.

7.20.3.4 Функция realloc

Краткое описание

#include <stdlib.h>
void *realloc(void *ptr, size_t size);

Описание

Realloc Функция освобождает старый объект, на который указывает ptr, и возвращает указатель на новый объект, размер которого указан по размеру. Содержание нового объект должен быть таким же, как у старого объекта до освобождения, до меньшего из новых и старых размеров. Любые байты в новом объекте, превышающие размер старого объекта, имеют неопределенные значения.

Если ptr является нулевым указателем, функция realloc ведет себя как функция malloc для указанный размер. В противном случае, если ptr не совпадает с указателем, ранее возвращенным функции calloc, malloc или realloc, или если пространство было освобождено вызовом для функции free или realloc поведение не определено. Если память для нового объект не может быть размещен, старый объект не освобожден и его значение не изменилось.

Возвращает

Функция realloc возвращает указатель на новый объект (который может иметь то же самое значение как указатель на старый объект), или нулевой указатель, если новый объект не может быть выделены.


Помимо редакционных изменений из-за дополнительных заголовков и функций, стандарт ISO / IEC 9899: 2011 говорит то же самое, что и C99, но в разделе 7.22.3 вместо 7.20.3.


Solaris 10 (SPARC Страница man для realloc гласит:

Функция realloc () изменяет размер указателя блока на ptr для размера байтов и возвращает указатель на (возможно, перемещенный) блок. Содержание будет неизменным вплоть до меньшего из новых и старых размеров. Если новый размер блока требует перемещения блока, пространство для предыдущего создания блока освобождается. Если новый размер больше, содержимое вновь выделенной части блока не определено. Если ptr равно NULL, realloc () ведет себя как malloc () для указанного размера. Если size равен 0, а ptr не является нулевым указателем, указанное пространство освобождается.

Это довольно явное утверждение «оно работает как free ()».

Тем не менее, то, что MacOS X 10.5 или BSD говорит что-то другое, подтверждает часть моего первого абзаца «Никто в здравом уме».


Конечно, имеется Обоснование C99 ... В нем говорится:

7.20.3 Функции управления памятью

Обработка нулевых указателей и запросов выделения нулевой длины в определении из этих функции были частично обусловлены желанием поддержать эту парадигму:

OBJ * p; // pointer to a variable list of OBJs
    /* initial allocation */
p = (OBJ *) calloc(0, sizeof(OBJ));
     /* ... */
     /* reallocations until size settles */
 while(1) {
    p = (OBJ *) realloc((void *)p, c * sizeof(OBJ));
         /* change value of c or break out of loop */
 }

Этот стиль кодирования, не обязательно одобренный Комитетом, как сообщается, широко распространен use.

Некоторые реализации вернули ненулевые значения для запросов на выделение нулевых байтов. Хотя эта стратегия имеет теоретическое преимущество, заключающаяся в различении «ничего» и «нуля» (нераспределенный указатель и указатель на пробел нулевой длины), она имеет более убедительный характер. Теоретический недостаток необходимости концепции объекта нулевой длины. Так как такие объекты не может быть объявлено, единственный способ, которым они могли бы появиться, было бы через такие запросы на распределение.

Комитет C89 решил не принимать идею объектов нулевой длины. Распределение поэтому функции могут возвращать нулевой указатель для запроса на выделение нулевых байтов. Обратите внимание, что эта обработка не исключает изложенную выше парадигму.

ТИХОЕ ИЗМЕНЕНИЕ В C89

Программа, которая опирается на запросы выделения нулевого размера, возвращающие ненулевой указатель будет вести себя по-другому.

[...]

7.20.3.4 Функция realloc

Допустим нулевой первый аргумент. Если первый аргумент не равен нулю, а второй аргумент равен 0, то вызов освобождает память, указанную первым аргументом, и нулевой аргумент может быть вернулся; C99 согласуется с политикой запрещения объектов нулевого размера.

Новая функция C99: была изменена функция realloc, чтобы было ясно, что объект освобождается, новый объект выделяется, а содержимое нового объекта совпадает с это из старого объекта до меньшего из двух размеров. C89 попытался указать, что новый объект был тем же объектом, что и старый объект, но мог иметь другой адрес. Это конфликты с другими частями стандарта, которые предполагают, что адрес объекта является постоянным во время его продолжительность жизни. Кроме того, реализации, которые поддерживают фактическое распределение, когда размер равен нулю, не обязательно верните нулевой указатель для этого случая. C89, по-видимому, требует нулевого возвращаемого значения, и Комитет счел это слишком ограничительным.


Томас Падрон-МакКарти заметил :

C89 прямо говорит: «Если размер равен нулю, а ptr не является нулевым указателем, объект, на который он указывает, является освобожденный «. Таким образом, они, кажется, удалили это предложение в C99?

Да, они удалили это предложение, потому что оно включено в первое предложение:

Функция realloc освобождает старый объект, на который указывает ptr

комната там; старый объект освобожден. Если запрошенный размер равен нулю, вы возвращаете все, что может вернуть malloc (0) , что часто (обычно) является нулевым указателем, но может быть ненулевым указателем, который также может быть возвращен в free () , но который не может быть законно разыменован.

14
ответ дан 18 December 2019 в 09:10
поделиться
realloc(ptr, 0);

эквивалентно free (ptr); (хотя я бы не рекомендовал его использовать как такие!)

Также: эти два вызова эквивалентны друг другу (но не бесплатны):

realloc(NULL,size)
malloc(size)
4
ответ дан 18 December 2019 в 09:10
поделиться

Последний - realloc (ptr, 0) - подходит близко. Он освободит любой выделенный блок и заменит его минимальным выделением (говорит моя страница Mac OS X 10.5). Проверьте свою локальную страницу руководства, чтобы узнать, что она делает в вашей системе.

То есть, если ptr указал на существенный объект, вы вернете большую часть его памяти.


Страница man на Debian Lenny согласен с Mitch и Jonathan ... действительно ли BSD действительно расходится с Linux в этом?


Со страницы man, из-за которой все обидно:

Функция realloc () пытается изменить размер выделенного к ptr к размеру и возвращает ptr. [...] Если размер равен нулю и ptr не равен NULL, новый, объект минимального размера выделяется, а исходный объект освобождается.


Справочные страницы linux и solaris очень чистые, а стандарт 89 года: realloc (ptr, 0) работает как free ( PTR) . Справочная страница Mac OS выше и стандарт, цитируемый Джонатаном, менее ясны, но, похоже, оставляют место, чтобы нарушить эквивалентность.

Мне было интересно , почему разница: «действовать как свободный» интерпретация кажется мне очень естественной. Обе реализации, к которым у меня есть доступ, включают в себя некоторую переменную среды, управляемую переменной среды , но версия BSD допускает много других опций. Некоторые примеры:

  MallocGuardEdges Если установлено, добавить защитную страницу до и после
 каждый большой блок. 
 MallocDoNotProtectPrelude    If set, do not add a guard page before large
                              blocks, even if the MallocGuardEdges envi-
                              ronment variable is set.

 MallocDoNotProtectPostlude   If set, do not add a guard page after large
                              blocks, even if the MallocGuardEdges envi-
                              ronment variable is set.

и

  MallocPreScribble Если установлено, заполнить память, которая была выделена
с 0xaa байтами. Это увеличивает вероятность
 капот, что программа делает предположения о
 содержимое только что выделенной памяти
 не удастся.
 MallocScribble               If set, fill memory that has been deallo-
                              cated with 0x55 bytes.  This increases the
                              likelihood that a program will fail due to
                              accessing memory that is no longer allo-
                              cated.

Возможно, «объект минимального размера» - это ничто (то есть эквивалент free ) в обычных режимах, но что-то с некоторыми охранниками на месте. Возьми это за то, что оно того стоит.

0
ответ дан 18 December 2019 в 09:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: