Безопасно ли использовать malloc? - PullRequest
8 голосов
/ 15 мая 2010

Кто-то сказал мне, что выделение с помощью malloc больше не безопасно, я не гуру C / C ++, но я кое-что сделал с malloc и C / C ++. Кто-нибудь знает о том, в какие риски я вхожу?

Цитируя его:

[..] Но в действительности слабым местом C / C ++ является безопасность, а ахиллесова пята - это действительно malloc и злоупотребление указателями. C / C ++ - это широко известный небезопасный язык. [..] Было бы мало приложений, в которых я бы не рекомендовал продолжать программирование на C ++. "

Ответы [ 12 ]

16 голосов
/ 15 мая 2010

Вероятно, что new в C ++ безопаснее , чем malloc(), но это автоматически не делает malloc() более небезопасным, чем это было раньше. Ваш друг сказал, почему он считает это небезопасным?


Однако вот несколько вещей, на которые следует обратить внимание:

1) С C ++ вам нужно быть осторожным, когда вы используете malloc() / free() и new / delete рядом в та же программа. Это возможно и допустимо, но все, что было выделено с malloc(), должно быть освобождено с free(), а не с delete. Точно так же все, что было выделено с new, должно быть освобождено с delete, и никогда с free(). (Эта логика идет еще дальше: если вы выделяете массив с new[], вы должны освободить его с помощью delete[], а не только с delete.) Всегда используйте соответствующие аналоги для выделения и освобождения для каждого объекта.

int* ni = new int;
free(ni);   // ERROR: don't do this!
delete ni;  // OK

int* mi = (int*)malloc(sizeof(int));
delete mi;  // ERROR!
free(mi);   // OK  

2) malloc() и new (опять-таки о C ++) не делают одно и то же. malloc() просто дает вам часть памяти для использования; new дополнительно вызовет конструктор (если имеется). Точно так же delete вызовет деструктор (если доступно), а free() - нет. Это может привести к проблемам, таким как неправильно инициализированные объекты (потому что конструктор не был вызван) или неосвобожденные ресурсы (потому что деструктор не был вызван).

3) C ++ new также позаботится о выделении нужного объема памяти для указанного типа, в то время как вам нужно вычислить это самостоятельно с помощью malloc():

int *ni = new int;
int *mi = (int*)malloc(sizeof(int));  // required amount of memory must be
                                      // explicitly specified!
                                      // (in some situations, you can make this 
                                      // a little safer against code changes by
                                      // writing  sizeof(*mi)  instead.)

Вывод:

В C ++ new / delete должно быть предпочтительнее, чем malloc() / free(), где это возможно. (В C new / delete недоступно, поэтому выбор будет очевиден.)

13 голосов
/ 15 мая 2010

[...] C / C ++ - это широко известный небезопасный язык. [...]

На самом деле, это неправильно. На самом деле, "C / C ++" даже не существует. Есть C , и есть C ++ . Они имеют некоторый (или, если хотите, большой) синтаксис, но на самом деле они очень разные языки .

Одна вещь, которой они сильно отличаются, это их способ управления динамической памятью. В способе C действительно используется malloc() / free(), и если вам нужна динамическая память, вы мало что можете сделать, кроме как использовать их (или несколько братьев и сестер malloc()).
Способ C ++ состоит в том, чтобы не (вручную) иметь дело с динамическими ресурсами (из которых память является один) на всех . Управление ресурсами передается нескольким хорошо реализованным и протестированным классам, предпочтительно из стандартной библиотеки, а затем выполняется автоматически. Например, вместо того, чтобы вручную работать с нулевыми символьными буферами, есть std::string, вместо того, чтобы вручную иметь дело с динамически размещенными массивами, там std:vector, вместо того, чтобы вручную иметь дело с открытыми файлами, есть семейство std::fstream потоков и т. Д .

8 голосов
/ 15 мая 2010

Ваш друг может говорить о:

  • Безопасность использования указателей в целом.Например, в C ++, если вы выделяете массив char с помощью malloc, задайте вопрос, почему вы не используете string или vector.Указатели не являются небезопасными, но код, который глючит из-за неправильного использования указателей:Из соображений безопасности большинство ОС очищают память перед тем, как передать ее процессу.В противном случае конфиденциальные данные из одного приложения могут быть переданы другому приложению.В ОС, которые этого не делают, вы можете утверждать, что существует небезопасность, связанная с malloc.Это действительно больше связано с free.

Также возможно, что ваш друг не знает, о чем говорит.Когда кто-то говорит «Х небезопасен», мой ответ таков: «Каким образом?».

3 голосов
/ 15 мая 2010

Может быть, ваш друг старше и не знаком с тем, как все работает сейчас - раньше я думал, что C и C ++ фактически одинаковы, пока не обнаружил много нового о языке, появившегося за последние 10 лет ( большинство моих учителей были парнями из Bell Laboratories старой школы, которые писали в основном на C и обладали только беглым знанием C ++ - и инженеры Bell Laboratories изобрели C ++!). Не смейся над ним / ней - возможно, ты когда-нибудь тоже будешь там!

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

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

2 голосов
/ 15 мая 2010

Это единственный способ выделять и освобождать память в C изначально. Если вы злоупотребляете им, это может быть так же небезопасно, как и все остальное. Microsoft предоставляет некоторые «безопасные» версии других функций, которые принимают дополнительный параметр size_t - может быть, ваш друг имел в виду нечто подобное? Если это так, возможно, он просто предпочитает calloc () вместо malloc ()?

1 голос
/ 15 мая 2010

Нет ничего плохого в malloc как таковом. Ваш друг, очевидно, подразумевает, что ручное управление памятью небезопасно и легко приводит к ошибкам. По сравнению с другими языками, где память управляется автоматически сборщиком мусора (не то, что утечки невозможны - сегодня никого не волнует, очищает ли программа после завершения работы, важно то, что что-то не перегружает память, пока программа бег).

Конечно, в C ++ вы бы вообще не трогали malloc (потому что он просто не функционально эквивалентен new и просто не делает то, что вам нужно, предполагая, что большую часть времени вы не делаете не хочу просто получить сырую память). Кроме того, можно полностью программировать с использованием методов, которые почти полностью исключают возможность утечек памяти и повреждения (RAII), но это требует опыта.

1 голос
/ 15 мая 2010

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

Сказать, что malloc небезопасно, все равно, что сказать: «Не используйте систему X, потому что она небезопасна».

До этого используйте malloc в C и new в C ++. Если вы используете malloc в C ++, люди будут на вас злиться, но в определенных случаях это нормально.

1 голос
/ 15 мая 2010

Если вы используете C, вы должны использовать malloc для выделения памяти, если у вас нет сторонней библиотеки, которая будет выделять / управлять вашей памятью для вас.

Конечно, у вашего друга есть мысль, что сложно написать безопасный код на C, особенно когда вы выделяете память и работаете с буферами. Но мы все это знаем, верно? :)

0 голосов
/ 19 июня 2019

Возможно, человек имел в виду возможность доступа к данным через malloc ()?

Malloc не влияет на содержимое региона, который он предоставляет, поэтому МОЖЕТ иметь возможность собирать данные из других процессов, используя неправильную область большой области и затем сканируя содержимое.

free () также не очищает память, поэтому, в принципе, данные, размещенные в динамически распределенных буферах, доступны.

Я знаю человека, который много лет назад использовал malloc для создания схемы межпроцессного взаимодействия, когда обнаружил, что malloc одинакового размера вернет адрес самого последнего блока free'd.

0 голосов

Использование malloc небезопасно, потому что невозможно написать крупномасштабное приложение и гарантировать, что каждый malloc освобождается эффективным способом. Таким образом, у вас будут тонны утечек памяти, которые могут или не могут быть проблемой ... , но , когда вы удваиваете free или используете неправильный delete и т. Д., Может привести к неопределенному поведению. Действительно, использование неправильного delete в C ++ обычно позволяет выполнить произвольный код.

Способ ONLY для кода, написанного на языке C или C ++, является безопасным - математически доказать всю программу с учетом ее зависимостей.

Современные безопасные для памяти языки защищены от этих типов ошибок до тех пор, пока базовая языковая реализация не уязвима (что действительно редко, потому что все они написаны на C / C ++, но по мере продвижения к аппаратным JVM, это проблема уйдет).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...