Безопасно ли использовать malloc?

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

цитировать:

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

11 ответов


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

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

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


вероятно, это правда, что c++'s new и безопасное чем 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 дополнительно вызовите contructor (если имеется). Аналогично,delete вызовет деструктор (если он доступен), в то время как free() не будет. Это может привести к проблемам, таким как неправильно инициализированные объекты (поскольку конструктор был вызван) или несвободные ресурсы (поскольку деструктор не вызывался).

3) С++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() там, где это возможно. (In C,new/delete нет в наличии, поэтому выбор был бы очевиден там.)


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

  • безопасность использования указателей в целом. Например, в C++ , если вы выделяете массив char с помощью malloc, спросите, почему вы не используете string или vector. Указатели не являются небезопасными, но код, который глючит из-за неправильного использования указателей.

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

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


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

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

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


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


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

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


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

сказав, что malloc небезопасно, это как сказать:"не используйте систему X, потому что она небезопасна".

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


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

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


Технически говоря, malloc никогда не был безопасным для начала, но в стороне, единственное, что я могу придумать, это печально известный "убийца ум" (OOM = out-of-memory), который использует ядро Linux. Ты можешь!--3-->читайте об этом если вы хотите. Кроме этого, я не вижу, как небезопасна.


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


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

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

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