Что такое код memset


Определение и использование Memset

Какова польза функции memset() ?.

Определение: Устанавливает первые num байты блока памяти, на которые указывает ptr, на указанное значение (интерпретируется как unsigned char).

Означает ли это, что он жестко кодирует значение в адресе памяти?

memset(&serv_addr,0,sizeof(serv_addr) — пример, который я пытаюсь понять.

Может ли кто-нибудь объяснить это ОЧЕНЬ упрощенным способом?

memset() — очень быстрая версия относительно простой операции:

То есть memset(b, c, l) устанавливает байты l , начинающиеся с адреса b , до значения c . Он просто делает это намного быстрее, чем в приведенной выше реализации.

memset() обычно используется для инициализации значений. Например, рассмотрим следующую структуру:

Если вы создаете один из них в стеке так:

Тогда значения в этой структуре будут undefined. Они могут быть равны нулю, они могут быть любыми значениями, которые произошли там, когда последняя часть последнего использовалась. Поэтому обычно вы должны следовать этой строке с помощью:

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

memset — это обычный способ установить область памяти в 0 независимо от типа данных. Можно сказать, что memset не заботится о типе данных и просто устанавливает все байты в ноль.

IMHO на С++ следует избегать memset , когда это возможно, поскольку он обходит безопасность типов, предоставляемую С++, вместо этого следует использовать конструктор или инициализацию как средство инициализации. memset, выполненный над экземпляром класса, также может непреднамеренно уничтожить:

a memset в экземпляре выше не будет правильно выполнять декремент счетчика ссылок.

Я предполагаю, что serv_addr — это локальная или глобальная переменная некоторого типа struct — возможно, struct sockaddr — (или, возможно, class ).

&serv_addr берет адрес этой переменной. Это действительный адрес, заданный как первый аргумент memset . Второй аргумент memset — это байт, который будет использоваться для заполнения (нулевой байт). Последний аргумент memset — это размер в байтах этой зоны памяти для заполнения, размер которой в вашем примере равен serv_addr .

Итак, этот вызов memset очищает глобальную или локальную переменную serv_addr , содержащую некоторые struct .

На практике компилятор GCC, когда он оптимизирует, будет генерировать для этого умный код, обычно разворачивая и вставляя его (на самом деле, он часто является встроенным, поэтому GCC может генерировать для него очень умный код).

MemSet Определение и использование

Я немного понимаю , что определение memset() есть. Тем не менее, я не понимаю , в чем смысл его для.

Определение: Устанавливает первые пит байт блока памяти, на который указывает PTR до указанного значения (интерпретируется как беззнаковое полукокса).

Так же этот жесткий код значения в адресах памяти?

memset(&serv_addr,0,sizeof(serv_addr) является примером того, что я пытаюсь понять.

Может кто-то пожалуйста, объясните, в очень упрощенном виде?

memset() очень быстрая версия относительно простой операции:

То есть, memset(b, c, l) установить l байтов , начиная с адреса b на значение c . Он просто делает это гораздо быстрее , чем в вышеприведенной реализации.

memset() обычно используется для инициализации значений. Для примера рассмотрим следующую структуру:

Если вы создаете один из них на стеке, как так:

Тогда значение в этих структурах будет неопределенными. Они могут быть равны нулю, то они могут быть любые значения оказались там с момента, когда эта часть стека использовался последний раз. Так обычно вы бы следовать этой линии с:

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

memset является обычным способом , чтобы установить область памяти на 0 , независимо от типа данных. Можно сказать , что memset не заботится о типе данных и просто устанавливает все байты к нулю.

ИМХО в C ++ следует избегать , memset если это возможно , так как он обходит безопасность типа , который обеспечивает C ++, а не следует использовать конструктор или инициализацию как средство инициализации. MemSet сделано в экземпляре класса может уничтожить что — то случайно:

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

Я предполагаю , что serv_addr некоторые локальной или глобальной переменной некоторых struct -Возможно типа struct sockaddr — (или , может быть class ).

&serv_addr принимает адрес этой переменной. Это действительный адрес, данные в качестве первого аргумента memset . Второй аргумент memset является байтами , которые будут использоваться для заполнения (нулевых байт). Последний аргумент memset является размер в байтах этой зоны памяти для заполнения, что размер этой serv_addr переменной в вашем примере.

Так что этот вызов memset очищает глобальную или локальную переменную , serv_addr содержащую некоторые struct .

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

В чем разница между memset и memcpy в C

Я прочитал заголовки функций, но я все еще не уверен, в чем именно разница с точки зрения вариантов использования.

6 ответов

memcpy() копирует из одного места в другое. memset() просто устанавливает все части памяти на одно и то же значение.

в приведенной выше строке первые 50 символов строки str равны * (или любому второму аргументу memset).

вышеуказанная строка копирует первые 50 символов str1 в str2.

memset() устанавливает для всех байтов в указанном буфере одинаковое значение, memcpy() копирует последовательность байтов из другого места в буфере.

memset устанавливает блок памяти в одно значение. memcpy копирует содержимое блока в другой блок.

возможно, вас заинтересует разница между memcpy и memmove . Оба делают то же самое, но последний работает, даже если источник и назначение перекрываются.

memset() используется для установки всех байтов в блоке памяти определенным значением типа char. Memset также хорошо играет только с char как это его значение инициализации.

memcpy() копирует байты из памяти. Этот тип копируемых данных не имеет значения,он просто создает байтовые копии.

memset fill с постоянным байт

недействительным *функцию memset(Void*, который с инт С, в size_t Н);

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

memcpy скопируйте площадью

недействительным *функции memcpy(Void *после дест пустоту константные *в src, size_t в Н);

Илон Маск рекомендует:  Тег blockquote

memcpy() копирует из одного места в другое. memset() просто устанавливает все части памяти на то же самое.

например, здесь задает длину строки строки str в * (или любой второй аргумент memset).

Самая опасная функция в мире С/С++

Проверяя много лет различные C/C++ проекты, я заявляю: самая неудачная и опасная функция — memset(). При использовании функции memset() допускают наибольшее количество ошибок, в сравнении с использованием других функций. Я понимаю, что мой вывод вряд ли потрясёт основы мироздания или невероятно ценен. Однако я думаю, читателям будет интересно узнать, почему я пришел к такому заключению.

Здравствуйте

Меня зовут Андрей Карпов. Я совмещаю много должностей и занятий. Но основное, что я делаю, это рассказываю программистам о пользе, которую может приносить статический анализ кода. Естественно я делаю это с корыстной целью, пытаясь заинтересовать читателей анализатором PVS-Studio. Впрочем, это не уменьшает интересность и полезность моих статей.

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

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

Например, одним из интересных наблюдений было, что программисты допускают ошибки при Copy-Paste чаще всего в самом конце. На эту тему предлагаю вниманию статью «Эффект последней строки».

Новое наблюдение

Теперь у меня есть ещё одно интересное наблюдение. Используя те или иные функции, программисты могут допускать ошибки. При этом вероятность допущения ошибки зависит от используемой функции. Другими словами, какие-то функции провоцируют ошибки, а какие-то — нет.

Так вот, я готов назвать функцию, при использовании которой есть наибольшая вероятность сесть в лужу.

Итак, победитель на глючность — функция memset!

Как так получилось — сложно сказать. Видимо у неё неудачный интерфейс. Плюс само её использование достаточно трудоемко и легко ошибиться, вычисляя значения фактических аргументов.

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

Всего у меня в базе 9055 ошибок. Это те ошибки, которые умеет находить анализатор PVS-Studio. Понятно, что он умеет далеко не всё. Однако большое количество найденных ошибок позволяет мне быть уверенным в своих выводах. Так вот, я посчитал, что с использованием функции memset() связано 329 ошибок.

Итого, около 3,6% ошибок в базе связано с функцией memset(). Это много!

Примеры


Давайте рассмотрим некоторые типовые примеры ошибок. Рассматривая их, я думаю, вы согласитесь, что с функцией memset() что-то не так. Она притягивает зло.

Для начала освежим в памяти как объявлена эта функция:

void * memset ( void * ptr, int value, size_t num );

  • ptr — Pointer to the block of memory to fill.
  • value — Value to be set. The value is passed as an int, but the function fills the block of memory using the unsigned char conversion of this value.
  • num — Number of bytes to be set to the value. ‘size_t’ is an unsigned integral type.

Пример N1 (проект ReactOS)

Ошибка в том, что в C и в C++ нельзя передавать массивы по значению (подробнее). Аргумент ‘dest’ является не чем иным как обыкновенным указателем. Поэтому оператор sizeof() вычисляет размер указателя, а не массива.

Вроде memset() и не виноват. Но с другой стороны, эта функция заполнит нулями только 4 или 8 байт (экзотические архитектуры не в счёт). Ошибка есть и произошла она при вызове функции memset().

Пример N2 (проект Wolfenstein 3D)

Похожая ошибка. Допущена она скорее всего по невнимательности. Переменная ‘var’ является указателем. А значит memset() вновь обнулит только часть структуры. На практике будет обнулён только член ‘name’.

Пример N3 (проект SMTP Client)

Очень распространенный паттерн ошибки, про который тем не менее осведомлено мало программистов. Дело в том, что функция memset() будет удалена компилятором. Буфер после вызова memset() более не используется. И компилятор в целях оптимизации удаляет вызов функции. С точки зрения языка C/C++ это не оказывает никакого влияния на поведение программы. Это действительно так. То, что приватная информация останется в памяти, никак не повлияет на работу программы.

Это не ошибка компилятора. И это не мои фантазии. Компилятор действительно удаляет вызовы memset(). Каждый раз, когда я описываю эту ошибку уязвимости, я получаю письма, где со мной начинают спорить. Я уже устал отвечать на эти письма. Поэтому прошу всех сомневающихся, прежде чем начинать дискуссию, внимательно познакомиться со следующими материалами:

Пример N4 (проект Notepad++)

Часто забывают, что третий аргумент функции memset() это не количество элементов, а размер буфера в байтах. Именно так и произошло в приведенном выше фрагменте кода. В результате, заполнена будет только четверть буфера (при условии, что размер типа ‘int’ равен 4 байтам).

Пример N5 (проект Newton Game Dynamics)

Имеем дело с опечаткой. Скорее всего кто-то поленился два раза набирать вызов функции memset(). Продублировали строчку. В одном месте заменили ‘faceOffsetHitogram’ на ‘mainSegmenst’, а в другом забыли.

Получается, что sizeof() вычисляет размер не того массива, который заполняется нулями. Вроде как функция memset() никак не виновата. Но неправильно будет работать именно она.

Пример N6 (проект CxImage)

Здесь присутствует лишний оператор sizeof(). Правильно размер вычислять так:

Но написали лишний sizeof() и получилась глупость:

Здесь оператор sizeof() вычисляет размер типа size_t. Именно такой тип имеет выражение.

Я знаю, что хочется возразить. Уже не первый раз ошибка связана с оператором sizeof(). Т.е. программист ошибается, вычисляя размер буфера. Однако причиной этих ошибок всё равно является функция memset(). Она устроена так, что приходится делать эти различные вычисления, в которых так легко ошибиться.

Пример N7 (проект WinSCP)

Функция memset() всеядна. Поэтому спокойно отнесётся, если вы перепутаете 2 и 3 аргумент. Именно так здесь и произошло. Эта функция заполняет 0 байт.

Пример N8 (проект Multi Theft Auto)

А вот ещё одна аналогичная ошибка. Кажется, разработчики Win32 API пошутили, когда создали вот такой макрос:

По смыслу это альтернатива memset(). Но надо быть внимательным. Обратите внимание, что меняется местами 2 и 3 аргумент.

Когда начинают использовать RtlFillMemory(), то относятся к ней как к memset(). И думают, что параметры у них совпадают. В результате возникают ошибки.

NULL есть ни что иное, как 0. Поэтому функция memset() заполнила 0 байт.

Пример N9 (проект IPP Samples)

Илон Маск рекомендует:  Что такое код scanf

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

Хотя некоторые из приведенных выше ошибок были найдены в кода на языке C++, к C++ они никакого отношения не имеют. Другими словами, это ошибки возникают при программировании в стиле языка C.

Следующая ошибка связана как раз с неправильным использованием memset() в C++ программе. Пример достаточно длинный, поэтому можете в него не всматриваться. Прочитайте описание ниже и всё станет понятно.

Функция memset() используется для инициализации массива, состоящих из объектов класса. Самая большая беда в том, что класс содержит виртуальные функции. Соответственно функция memset() не только обнуляет поля класса, но и указатель на таблицу виртуальных методов (vptr). К чему это приведёт неизвестно. Но ничего хорошего в этом точно нет. Нельзя так обращаться с классами.

Заключение

Как видите, функция memset() имеет крайне неудачный интерфейс. В результате, функция memset() больше всех остальных провоцирует появление ошибок. Будьте бдительны!

Я не готов сейчас сказать, как можно использовать моё наблюдение. Но надеюсь, вам было интересно познакомиться с этой заметкой. Возможно теперь, используя memset(), вы будете более внимательны. И это уже хорошо.

Спасибо всем за внимание и подписывайтесь на мой твиттер @ Code_Analysis .

Примечание

Уже после публикации статьи, один из читателей прислал ссылку вот на эту интересную статью «memset is Evil». Решил поделиться ей с вами. Что-ж, ещё одно подтверждение опасности memset().

Найдите ошибки в своем C, C++, C# и Java коде

Предлагаем попробовать проверить код вашего проекта с помощью анализатора кода PVS-Studio. Одна найденная в нём ошибка скажет вам о пользе методологии статического анализа кода больше, чем десяток статей.

Определение и использование Memset

Какова полезность функции memset() ?.

Определение: задает первые num байт блока памяти, на который указывает ptr
указанное значение (интерпретируется как беззнаковый символ).

Означает ли это, что он жестко кодирует значение в адресе памяти?

memset(&serv_addr,0,sizeof(serv_addr) это пример, который я пытаюсь понять.

Может кто-нибудь объяснить очень упрощенно?

6 ответов

memset() обычно используется для инициализации значений. Например рассмотрим следующую структуру:

Если вы создаете один из них в стеке, как так:

Тогда значения в этой структуре будут неопределенными. Они могут быть нулевыми, они могут быть любыми значениями, которые были там с момента последнего использования этой части стека. Так что обычно вы будете следовать этой линии с:

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

memset() очень быстрая версия относительно простой деятельности:

То есть memset(b, c, l) задайте значение l байт, начиная с адреса b c . Он просто делает это намного быстрее, чем в приведенной выше реализации.

Я думаю, что serv_addr это какая-то локальная или глобальная переменная какого struct — то типа-возможно struct sockaddr — (или, возможно, a class ).

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

Таким образом, этот вызов memset очищает глобальную или локальную переменную serv_addr , содержащую некоторые struct .

На практике компилятор GCC, когда он оптимизируется, будет генерировать умный код для этого, обычно разворачивая и вставляя его (на самом деле, это часто встроенный, поэтому GCC может генерировать очень умный код для него).

memset это распространенный способ установить область памяти в 0 независимо от типа данных. Можно сказать, что memset не заботится о типе данных и просто устанавливает все байты в ноль.

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

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

Это не что иное, как установка памяти на определенное значение.

Вот пример кода.

Memset (const *p, unit8_t V , unit8_t L), здесь p-указатель на целевую память, V-значение целевого буфера, которому будет присвоено значение V, а l-длина данных.

memset — набор байт в памяти

void * memset(void *s, int c,size_t n)

Описание — функция memset () копирует c (преобразуется в беззнаковый символ) в каждый из первых n байтов объекта, на который указывает s.
Здесь для вышеуказанной функции memset () возвращает значение s.

Функция memset

Функция memset() копирует младший байт параметра ch в первые count символов массива, адресуемого параметром buf . Функция возвращает значение указателя buf .


Чаще всего функция memset() используется для инициализации области памяти некоторым известным значением.

Пример

Данный фрагмент инициализирует первые 100 байтов массива, адресуемого указателем buf , нулями. Затем он помещает символы X в первые 10 байтов этого массива и выводит строку XXXXXXXXXX.

Memset Определение и использование

В чем полезность функции memset() ?

Определение : Устанавливает первые n байтов блока памяти, указанного указателем ptr, в указанное значение (интерпретируется как символ без знака).

Означает ли это, что он жестко кодирует значение в адресе памяти?

memset(&serv_addr,0,sizeof(serv_addr) — это пример, который я пытаюсь понять.

Может кто-нибудь объяснить, пожалуйста, в очень упрощенном виде?

6 ответов

memset() — это очень быстрая версия относительно простой операции:

То есть memset(b, c, l) устанавливает байты l начинающиеся с адреса b на значение c . Он просто делает это намного быстрее, чем в приведенной выше реализации.

memset() обычно используется для инициализации значений. Например, рассмотрим следующую структуру:

Если вы создадите один из них в стеке так:

Тогда значения в этой структуре будут неопределенными. Они могут быть равны нулю, они могут быть любыми значениями, которые были там, когда последний раз использовалась эта часть стека. Поэтому обычно вы будете следовать этой строке:

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

memset — это обычный способ установить область памяти на 0 независимо от типа данных. Можно сказать, что memset не заботится о типе данных и просто устанавливает все байты в ноль.

ИМХО в C ++ следует избегать использования memset когда это возможно, поскольку это обходит безопасность типов, которую обеспечивает C ++, вместо этого следует использовать конструктор или инициализацию в качестве средства инициализации. memset, выполненный на экземпляре класса, также может непреднамеренно уничтожить что-либо:

memset в экземпляре выше не будет правильно уменьшать счетчик ссылок.

Илон Маск рекомендует:  Шаблон сайта деревянный забор HTML, CSS, JavaScripts, 1 страница

Я предполагаю, что serv_addr — это некоторая локальная или глобальная переменная некоторого типа struct sockaddr — возможно, struct sockaddr — (или, возможно, class ).

&serv_addr получает адрес этой переменной. Это действительный адрес, указанный как первый аргумент memset . Второй аргумент memset — это байт, который будет использоваться для заполнения (нулевой байт). Последний аргумент memset — это размер в байтах той зоны памяти, которую нужно заполнить, это размер этой переменной serv_addr в вашем примере.

Таким образом, этот вызов memset очищает глобальную или локальную переменную serv_addr содержащую некоторую struct .

На практике, компилятор GCC , когда он оптимизирует, будет генерировать умный код для этого, обычно разворачивая и вставляя его (на самом деле, он часто является встроенным, поэтому GCC может генерировать очень умный код для него).

Это не что иное, как установка памяти на определенное значение.

Вот пример кода.

Memset (const * p, unit8_t V, unit8_t L), где P — указатель на целевую память, V — значение для целевого буфера, для которого будет установлено значение V, а l — длина данных.

memset — устанавливает байты в памяти

void * memset (void * s, int c, size_t n)

Описание — функция memset () должна копировать c (преобразованный в беззнаковый символ) в каждый из первых n байтов объекта, на который указывает s. Здесь для вышеуказанной функции memset () должна возвращать значение s.

c++ habr Определение и использование Memset

memset си реализация (5)

Это не что иное, как установление памяти в особую ценность.

Вот пример кода.

Memset (const * p, unit8_t V, unit8_t L) Здесь P является указателем на целевую память, V — значением целевого буфера, который будет установлен в значение V, а l — длина данных.

Я немного понимаю, что такое определение memset() . Однако я не понимаю, для чего это важно.

Определение: Устанавливает первые num байты блока памяти, на которые указывает ptr, на указанное значение (интерпретируется как unsigned char).

Значит ли этот жесткий код значение в адресе памяти?

memset(&serv_addr,0,sizeof(serv_addr) — пример, который я пытаюсь понять.

Может ли кто-нибудь объяснить это ОЧЕНЬ упрощенным способом?

Я полагаю, что serv_addr — это локальная или глобальная переменная какого-либо типа struct sockaddr — возможно, struct sockaddr — (или, может быть, class ).

&serv_addr берет адрес этой переменной. Это действительный адрес, заданный как первый аргумент memset . Второй аргумент memset — это байт, который будет использоваться для заполнения (нулевой байт). Последний аргумент memset — это размер в байтах этой зоны памяти для заполнения, который является размером этой переменной serv_addr в вашем примере.

Таким образом, этот вызов memset очищает глобальную или локальную переменную serv_addr содержащую некоторую struct .

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

memset() — очень быстрая версия относительно простой операции:

То есть memset(b, c, l) устанавливает l байт, начиная с адреса b до значения c . Он просто делает это намного быстрее, чем в приведенной выше реализации.

memset-set байтов в памяти

void * memset (void * s, int c, size_t n)

Описание. Функция memset () должна копировать c (преобразован в unsigned char) в каждый из первых n байтов объекта, на который указывает s. Здесь для указанной функции memset () возвращает значение s.

memset() обычно используется для инициализации значений. Например, рассмотрим следующую структуру:

Если вы создадите один из них в стеке так:

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

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

Как использовать прототип memset

void *memset( const void *str, int ch, size_t n ); Вот, как выглядит прототип memset(). Не могу понять как написать с ним программу даже самую примитивную с использованием прототипа memset(). Только с использованием массива типа int.

1 ответ 1

Не уверен, что понял ваш вопрос правильно. вам нужна реализация стандартной функции memset ?

У вас, кстати, неправильный заголовок — первый параметр не может быть const , потому что функция должна его модифицировать.

Оптимизированная версия, копирует 8-байтовыми словами:

Вопрос по memset, coredump, c-strings, pointers, c++ &#8211 memset не работает с указателем на символ

Что не так со следующим кодом? memset должен работать с указателем на блок памяти для заполнения. Но этот код отображает проблему в консоли, говоря о ошибке сегментации (ядро сброшено)

«SAMPLE TEXT» ). Это не разрешено

и UB когда-либо раньше. Это UB в C.

C ++ ≥11: Вы не можете назначать строковые литералы const char указатели.

C ++ ≥98 и C: вы не можете перезаписать строковые литералы.

измени свой код на

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

++, унаследованной от C и датируемой временем, когдабыло нет такой вещи, как const , Строковые литералы имеют тип const char [n] , но если вы не скажете своему компилятору, что вам не нужно быть совместимым с кодом до 1990 года, он молча позволит вам установить char * переменные, чтобы указать на них. Но этоне будет позволяют писать через такой указатель. Фактическая память помечена (по возможности) только для чтения; наблюдаемая ошибка «ошибка сегментации» — это то, как операционная система сообщает о попытке записи в постоянную память.

С точки зрения спецификации языка, написание const данные через не const указатель — как бы вам ни удалось его настроить — имеет «неопределенное поведение», что является причудливым способом сказать «программа неверна, но компилятору не нужно выдавать диагностику, и если вы получаете скомпилированный исполняемый файл, он может сделатьчто-нибудь«Ошибка сегментации» почти всегда означает, что ваша программа где-то имеет неопределенное поведение.

Если я компилирую вашу программу с соответствующими настройками, я получаю сообщение об ошибке:

Пока вы не наберете достаточно навыков, чтобы знать, когда более подходящими являются различные настройки, скомпилируйтевсе ваши программы на C ++ с -std=gnu++11 -Wall -Werror или каким бы ни был эквивалент вашего компилятора. (Похоже, вы используете операционную систему Unix-flavor, поэтому эти настройки должны работать. -g и / или -O .)

Вашу программу можно заставить работать, изменив ее на чтение

Изменение, которое исправляет ошибку char *name в char name[] ; Я изменил несколько других вещей, но только для того, чтобы продемонстрировать лучший стиль. Это заставляет компилятор копировать строковый литерал взаписываемый память при входе в main . Зачем это займет слишком много времени, чтобы объяснить здесь; обратитесь к хорошему учебнику по С ++.

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL