segmentation fault core dumped как исправить

Обработка Segmentation Fault в C++

Вводная

C++ является «небезопасным» («unmanaged») языком, поэтому программы могут «вылетать» — аварийно завершать работу без сохранения данных пользователя, сообщения об ошибке и т.п. — стоит только, например, залезть в не инициализированную память. Например:

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

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

Способ 1: SEH

Если Вы используете OS Windows в качестве целевой ОС и Visual C++ в качестве компилятора, то Вы можете использовать Structured Exception Handling — расширение языка С++ от Microsoft, позволяющее отлавливать любые исключения, происходящие в программе.

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

Вот «работающий пример» — «скопируй и вставь в Visual Studio»

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

Данная методика, при всей ее привлекательности, имеет ряд минусов:

Минусов оказалось настолько много, что приходится искать второе решение.

Способ 2: POSIX — сигналы

Способ рассчитан на то, что в момент падения программа получает POSIX-сообщение SIGSEGV. Это безусловно так во всех UNIX-системах, но это фактически так (хотя никто не гарантировал, windows — не posix-совместима) и в windows тоже.

Методика простая — мы должны написать обработчик сообщения SIGSEGV, в котором программа совершит «прощальные действия» и, наконец, упадет:

после чего мы должны зарегистрировать этот обработчик:

Вот готовый пример:

В отличие от SEH, это работает всегда: решение «многопоточное» (вы можете уронить программу в любом потоке, обработчик запустится в любом случае) и «кроссплатформенное» — работает под любым компилятором, и под любой POSIX-совместимой ОС.

Источник

указатели — C ++ Segmentation Fault — Core Dumped

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

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

Он читает несколько файлов ISBN из файла и проверяет, действительны они или нет.

Хотя может показаться, что это много, логика очень проста.

Любая помощь приветствуется!

Решение

Я постарался подробно описать как можно больше очевидных ошибок ниже. Там может быть гораздо больше. При таком количестве ошибок очевидно, что вы используете неправильный подход к программированию. Во-первых, вы должны четко подумать о коде, который вы пишете, недостаточно написать что-то, что выглядит примерно правильно, с программированием вы должны его получить именно так право. Во-вторых, вы пишете слишком много некачественного кода. Вы должны написать несколько строк кода, заставить их работать, прежде чем писать больше. Вы накапливали ошибку за ошибкой, поэтому очевидно, что вы проводили нулевое тестирование. Это не способ даже для профессионала работать, не говоря уже о новичке. И работать значит работать, а не просто компилировать. Как показывает этот код, легко написать множество кода, который компилируется. Наконец научитесь использовать отладчик, он поможет загрузке. Очевидно, у вас есть какая-то сложная система клиент / сервер. Просто забудьте об этом, установите компилятор и отладчик на свой компьютер.

это то, что вы хотите. Не используйте reinterpret_cast, если вы действительно не знаете, что делаете.

неправильный способ проверки конца файла

это то, что вы хотите.

На самом деле весь void setListOfIsbn(const string filename, list &listOfIsbn) это слишком сложно. Это делает то же самое, но в три раза меньше кода

потому что isbnCodeReform является строкой нулевой длины, так isbnCodeReform[i] собирается потерпеть неудачу. Возможно, вы имели в виду это

Опять продукты это массив нулевой длины, так products[i] не удастся. Опять вы, вероятно, имели в виду что-то вроде

Это путаница в том, как работают итераторы

Вы могли бы написать

или вы могли бы написать

То, что у вас есть, является смесью двух, которая не работает.

Другие решения

Ошибка происходит здесь:

Где вы приводите символ (скорее всего, цифру) к const char * — поэтому у нас есть значение символа, используемого в качестве указателя. Что почти наверняка даст сбой в любой системе, которая вообще проверяет доступ к памяти.

Вы должны добавить символ к вашей строке. Самый простой способ это:

Источник

Ошибка сегментирования Ubuntu

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

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

Что такое ошибка сегментации?

Ошибка сегментации, Segmentation fault, или Segfault, или SIGSEGV в Ubuntu и других Unix подобных дистрибутивах, означает ошибку работы с памятью. Когда вы получаете эту ошибку, это значит, что срабатывает системный механизм защиты памяти, потому что программа попыталась получить доступ или записать данные в ту часть памяти, к которой у нее нет прав обращаться.

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

Допустим, в вашей системе есть 6 Гигабайт оперативной памяти, каждой программе нужно выделить определенную область, куда будет записана она сама, ее данные и новые данные, которые она будет создавать. Чтобы дать возможность каждой из запущенных программ использовать все шесть гигабайт памяти был придуман механизм виртуального адресного пространства. Создается виртуальное пространство очень большого размера, а из него уже выделяется по 6 Гб для каждой программы. Если интересно, это адресное пространство можно найти в файле /proc/kcore, только не вздумайте никуда его копировать.

Выделенное адресное пространство для программы называется сегментом. Как только программа попытается записать или прочитать данные не из своего сегмента, ядро отправит ей сигнал SIGSEGV и программа завершится с нашей ошибкой. Более того, каждый сегмент поделен на секции, в некоторые из них запись невозможна, другие нельзя выполнять, если программа и тут попытается сделать что-то запрещенное, мы опять получим ошибку сегментации Ubuntu.

Почему возникает ошибка сегментации?

И зачем бы это порядочной программе лезть, куда ей не положено? Да в принципе, незачем. Это происходит из-за ошибки при написании программ или несовместимых версиях библиотек и ПО. Часто эта ошибка встречается в программах на Си или C++. В этом языке программисты могут вручную работать с памятью, а язык со своей стороны не контролирует, чтобы они это делали правильно, поэтому одно неверное обращение к памяти может обрушить программу.

Что делать если возникла ошибка сегментирования?

Если вы думаете, что это ошибка в программе, то вам остается только отправить отчет об ошибке разработчикам. Но вы все-таки еще можете попытаться что-то сделать.

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

sudo apt update
sudo apt full-upgrade

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

/.cache. Просто удалите папки программы и попробуйте снова ее запустить. Если и это не помогло, вы можете попробовать полностью удалить программу, а потом снова ее установить, возможно, какие-нибудь зависимости были повреждены:

sudo apt remove пакет_программы
sudo apt autoremove
sudo apt install пакет_программы

Если есть возможность, попробуйте установить программу из другого источника, например, не из PPA, а более старую версию, из официальных репозиториев.

Когда вы все это выполнили, скорее всего, проблема не в вашем дистрибутиве, а в самой программе. Нужно отправлять отчет разработчикам. В Ubuntu это можно сделать с помощью программы apport-bug. Обычно Ubuntu предлагает это сделать сразу, после того как программа завершилась с ошибкой сегментирования. Если же ошибка сегментирования Ubuntu встречается не в системной программе, то вам придется самим искать разработчиков и вручную описывать что произошло.

Чтобы помочь разработчикам решить проблему, недостаточно отправить им только сообщение что вы поймали Segmentation Fault, нужно подробно описать проблему, действия, которые вы выполняли перед этим, так чтобы разработчик мог их воспроизвести. Также, желательно прикрепить к отчету последние функции, которые вызывала программа (стек вызовов функций), это может очень сильно помочь разработчикам.

Рассмотрим, как его получить. Это не так уж сложно. Сначала запустите вашу программу, затем узнайте ее PID с помощью команды:

Дальше запускаем отладчик gdb:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Подключаемся к программе:

(gdb) attach ваш_pid

После подключения программа станет на паузу, продолжаем ее выполнение командой:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Затем вам осталось только вызвать ошибку:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

И набрать команду, которая выведет стек последних вызовов:

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

(gdb) detach
(gdb) quit

Дальше остается отправить отчет и ждать исправления ошибки. Если вы не уверены, что ошибка в программе, можете поспрашивать на форумах. Когда у вас есть стек вызовов, уже можно попытаться, если не понять в чем проблема, то попытаться узнать, не сталкивался ли с подобной проблемой еще кто-то.

Выводы

Теперь у вас есть приблизительный план действий, что нужно делать, когда появляется ошибка сегментирования сделан дамп памяти ubuntu. Если вы знаете другие способы решить эту проблему, напишите в комментариях!

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Оцените статью:

Об авторе

Основатель и администратор сайта losst.ru, увлекаюсь открытым программным обеспечением и операционной системой Linux. В качестве основной ОС сейчас использую Ubuntu. Кроме Linux, интересуюсь всем, что связано с информационными технологиями и современной наукой.

7 комментариев

Спасибо, было очень интересно почитать про отладчик.

На самом деле от этого избавится я не могу. Остаётся мне всё сваливать на свой старый компьютер с 1024 мегабайтами озу. Постоянные ошибки сегментирования когда комплимирую какую-либо программу. Чтобы скомплимировать ядро надо по миллиону раз вводить make!! Щас выкину комп и куплю новый и думаю проблема сама разрешится.

Gentoo. cmake 3.14.6. Segmentation fault.
Xeon 2620 v2 24Gb ram

Проблема сама не решается почему-то. 8-(

С ошибкой SIGSEGV или так называемой ошибкой сегментации(на самом деле это ошибки обращения с памятью) вы ничё не сможете сделать. если вы юзер, а не разработчик и она возникает в вашей проге. можете только одного не запускать эту прогу удалить её или попытаться обновить, возможно(вовсе не обязательно!) её заметили и исправили. Но вообще лицензионное соглашение по Ubuntu вас предупреждает, что вы пользуетесь системой в которой софт вовсе не обязан работать и никто за это не отвечает. вы это делаете на свой страх и риск! это краткий его перевод. А если вы купили операционку заплатили бабки и заказали техподдержку, то вы тогда уже имеете право обратиться в службу тех поддержки сообщить баг, где и как он возникает и они обязаны не просто испавить его прислав патч, но так же всем таким как вы кто заплатил. Иначе вы имеете право подать на них в суд и они обязаны компенсировать вам убытки. Но это не Ubuntu. Обратная сторона медали свободного по и бесплатных операционок. среди Линуксовых есть AIX(только платная+ техподдержка), SUSE(не путать с Open Suse) и Debian(есть free урезаный вариант и нормальный платный). Это оч серьёзная ошибка краеугольный камень всех программ и работы компа в целом. Если это ломается, то всё летит к чёрту. Конечно они стараюстся и сразу посылать вас не будут. Это их репутация! но вообще дело в програмерах. Щаз стало оч много криворуких. Вот я смотрю на их код и удивляюсь, как можно так безалаберно писать проги! Если бы вы только это видели вы бы не удивились почему всё так плохо работает. Встречаются такие кадры которые всё только портят! ну а что програмеров не хаватет, делать надо много вот и берут всех подряд. А потом начинается. Если конечно это заметили до релиза, то ладно. Но тут всё ещё зависит от тестеров. Если они хорошие то найдут баги вовремя до релиза и исправят. но у нас как бывает. Отдела тестирования нет, сэкономили.. Тестер дай бог 2-3 а то часто 1 вообще. В программе всегда много ошибок. Особенно вначале. все мы ошибаемся, особенно некоторые. Причина? Нехватка мозгов или банально невнимательность. поэтому все проги должны быть тщательнейшим образом оттестированы. только тогда она может быть допущена к релизу. А ещё заказчик подгоняет. Хорошую прогу нельзя написать в спешке. тем более большую. Такие ошибки как оч трудно найти, а если она не всегда воспроизводится, так вообще нереально, Если только случайно наткнёшься. Потому что как бывает один раз вылетела, а второй нет и пошла дальше и норм. Или пошла дальше и всё стало неправильным. с програмой начинают твориться чудеса. это всё та же ошибка с памятью, которая всё портит. Вылететь может не только ваша прога но и вся система. Но даже если она стабильно воспроизводится, то на её поиск может понадобиться дни а может и неделя две кропотливой упорной работы, носящей изнуряющий характер. искать будут всем отделом. но её тогда по крайней мере можно найти. а если нет. то вам поможет только чудо. А уж что сделают после этого с тем кто это сделал я даже не знаю! Вот такие вот они эти ошибки сегментации. Я показал то что там происходит за кадром юзера.

У меня появляется такая ошибка при попытке запуска Viber

Источник

Segmentation Fault (распределение памяти компьютера)

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Когда я делаю ошибку в коде, то обычно это приводит к появлению сообщения “segmentation fault”, зачастую сокращённого до “segfault”. И тут же мои коллеги и руководство приходят ко мне: «Ха! У нас тут для тебя есть segfault для исправления!» — «Ну да, виноват», — обычно отвечаю я. Но многие ли из вас знают, что на самом деле означает ошибка “segmentation fault”?

Чтобы ответить на этот вопрос, нам нужно вернуться в далёкие 1960-е. Я хочу объяснить, как работает компьютер, а точнее — как в современных компьютерах осуществляется доступ к памяти. Это поможет понять, откуда же берётся это странное сообщение об ошибке.

Вся представленная ниже информация — основы компьютерной архитектуры. И без нужды я не буду сильно углубляться в эту область. Также я буду применять всем известную терминологию, так что мой пост будет понятен всем, кто не совсем на «вы» с вычислительной техникой. Если же вы захотите изучить вопрос работы с памятью подробнее, то можете обратиться к многочисленной доступной литературе. А заодно не забудьте покопаться в исходном коде ядра какой-нибудь ОС, например, Linux. Я не буду излагать здесь историю вычислительной техники, некоторые вещи не будут освещаться, а некоторые сильно упрощены.

Немного истории

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

То есть на ОС приходилась, скажем, четверть всей доступной памяти, а остальной объём отдавался под пользовательские задачи. В то время роль ОС заключалась в простом управлении оборудованием с помощью прерываний ЦПУ. Так что операционке нужна была память для себя, для копирования данных с устройств и для работы с ними (режим PIO). Для вывода данных на экран нужно было использовать часть основной памяти, ведь видеоподсистема либо не имела своей оперативки, либо обладала считанными килобайтами. А уже сама программа выполнялась в области памяти, идущей сразу после ОС, и решала свои задачи.

Совместный доступ к ресурсам

Из-за непомерной стоимости мало кто мог позволить себе приобрести сразу несколько компьютеров, чтобы обрабатывать одновременно несколько задач. Поэтому люди начали искать способы совместного доступа к вычислительным ресурсам одного компьютера. Так наступила эра многозадачности. Обратите внимание, что в те времена ещё никто не помышлял о многопроцессорных компьютерах. Так как же можно заставить компьютер с одним ЦПУ выполнять несколько разных задач?

Решением стало использование планировщика задач (scheduling): пока один процесс прерывался, ожидая завершения операций ввода/вывода, ЦПУ мог выполнять другой процесс. Я не буду здесь больше касаться планировщика задач, это слишком обширная тема, не имеющая отношения к памяти.

Если компьютер способен поочерёдно выполнять несколько задач, то распределение памяти будет выглядеть примерно так:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

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

Когда один программист будет писать код для выполнения задачи В, он должен знать границы выделяемых сегментов памяти. Допустим, задача В занимает в памяти отрезок от 10 до 12 Кб, тогда каждый адрес памяти должен быть жёстко закодирован в пределах этих границ. Но если компьютер будет выполнять сразу три задачи, то память будет поделена на большее количество сегментов, и значит сегмент для задачи В может оказаться сдвинут. Тогда код программы придётся переписывать, чтобы она могла оперировать меньшим объёмом памяти, а также изменить все указатели.

Здесь всплывает и иная проблема: что если задача В обратится к сегменту памяти, выделенному для задачи А? Такое легко может произойти, ведь при работе с указателями памяти достаточно сделать маленькую ошибку, и программа будет обращаться к совершенно другому адресу, нарушив целостность данных другого процесса. При этом задача А может работать с очень важными с точки зрения безопасности данными. Нет никакого способа помешать В вторгнуться в область памяти А. Наконец, вследствие ошибки программиста задача В может перезаписать область памяти ОС (в данном случае от 0 до 4 Кб).

Адресное пространство

Чтобы можно было спокойно выполнять несколько задач, хранящихся в памяти, нам нужна помощь от ОС и оборудования. В частности, адресное пространство. Это некая абстракция памяти, выделяемая ОС для какого-то процесса. На сегодняшний день это фундаментальная концепция, которая используется везде. По крайней мере, во ВСЕХ компьютерах гражданского назначения принят именно этот подход, а у военных могут быть свои секреты. Персоналки, смартфоны, телевизоры, игровые приставки, умные часы, банкоматы — ткните в любой аппарат, и окажется, что распределение памяти в нём осуществляется по принципу «код-стек-куча» (code-stack-heap).

Адресное пространство содержит всё, что нужно для выполнения процесса:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Виртуализация памяти

Допустим, задача А получила в своё распоряжение всю доступную пользовательскую память. И тут возникает задача В. Как быть? Решение было найдено в виртуализации.

Напомню одну из предыдущих иллюстраций, когда в памяти одновременно находятся А и В:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Допустим, А пытается получить доступ к памяти в собственном адресном пространстве, например по индексу 11 Кб. Возможно даже, что это будет её собственный стек. В этом случае ОС нужно придумать, как не подгружать индекс 1500, поскольку по факту он может указывать на область задачи В.

На самом деле, адресное пространство, которое каждая программа считает своей памятью, является памятью виртуальной. Фальшивкой. И в области памяти задачи А индекс 11 Кб будет фальшивым адресом. То есть — адресом виртуальной памяти.

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

Таким образом, каждое обращение к памяти регулируется операционной системой. И это должно осуществляться очень эффективно, чтобы не слишком замедлять работу различных выполняющихся программ. Эффективность обеспечивается с помощью аппаратных средств, преимущественно — ЦПУ и некоторых компонентов вроде MMU. Последний появился в виде отдельного чипа в начале 1970-х, а сегодня MMU встраиваются непосредственно в процессор и в обязательном порядке используются операционными системами.

Вот небольшая программка на С, демонстрирующая работу с адресами памяти:

На моей машине LP64 X86_64 она показывает такой результат:

Code is at 0x40054c
Stack is at 0x7ffe60a1465c
Heap is at 0x1ecf010

Как я и описывал, сначала идёт кодовый сегмент, затем куча, а затем стек. Но все эти три адреса фальшивые. В физической памяти по адресу 0x7ffe60a1465c вовсе не хранится целочисленная переменная со значением 3. Никогда не забывайте, что все пользовательские программы манипулируют виртуальными адресами, и только на уровне ядра или аппаратных драйверов допускается использование адресов физической памяти.

Переадресация

Переадресация (транслирование, перевод, преобразование адресов) — это термин, обозначающий процесс сопоставления виртуального адреса физическому. Занимается этим модуль MMU. Для каждого выполняющегося процесса операционка должна помнить соответствия всех виртуальных адресов физическим. И это довольно непростая задача. По сути, ОС приходится управлять памятью каждого пользовательского процесса при каждом обращении. Тем самым она превращает кошмарную реальность физической памяти в полезную, мощную и лёгкую в использовании абстракцию.

Давайте рассмотрим подробнее.

Итак, это виртуальное адресное пространство:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

А это его физический образ:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Физический адрес = виртуальный адрес + base

Если получившийся физический адрес (6 Кб) выбивается из границ выделенной области (4—20 Кб), это означает, что процесс пытается обратиться к памяти, которая ему не принадлежит. Тогда ЦПУ генерирует исключение и сообщает об этом ОС, которая обрабатывает данное исключение. В этом случае система обычно сигнализирует процессу о нарушении: SIGSEGV, Segmentation Fault. Этот сигнал по умолчанию прерывает выполнение процесса (это можно настраивать).

Перераспределение памяти

Если задача А исключена из очереди на выполнение, то это даже лучше. Это означает, что планировщик попросили выполнить другую задачу (допустим, В). Пока выполняется В, операционка может перераспределить всё физическое пространство задачи А. Во время выполнения пользовательского процесса ОС зачастую теряет управление процессором. Но когда процесс делает системный вызов, процессор снова возвращается под контроль ОС. До этого системного вызова операционка может что угодно делать с памятью, в том числе и целиком перераспределять адресное пространство процесса в другой физический раздел.

В нашем примере это осуществляется достаточно просто: ОС перемещает 16-килобайтную область в другое свободное место подходящего размера и просто обновляет значения переменных base и bounds для задачи А. Когда процессор возвращается к её выполнению, процесс переадресации всё ещё работает, но физическое адресное пространство уже изменилось.

С точки зрения задачи А ничего не меняется, её собственное адресное пространство по-прежнему расположено в диапазоне 0-16 Кб. При этом ОС и MMU полностью контролируют каждое обращение задачи к памяти. То есть программист манипулирует виртуальной областью 0-16 Кб, а MMU берёт на себя сопоставление с физическими адресами.

После перераспределения образ памяти будет выглядеть так:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Программисту теперь не нужно заботиться о том, с какими адресами памяти будет работать его программа, не нужно переживать о конфликтах. ОС в связке с MMU снимают с него все эти заботы.

Сегментация памяти

В предыдущих главах мы рассмотрели вопросы переадресации и перераспределения памяти. Однако у нашей модели работы с памятью есть ряд недостатков:

Для решения некоторых из этих проблем давайте рассмотрим более сложную систему организации памяти — сегментацию. Смысл её прост: принцип “base and bounds” распространяется на все три сегмента памяти — кучу, кодовый сегмент и стек, причём для каждого процесса, вместо того чтобы рассматривать образ памяти как единую уникальную сущность.

В результате мы больше не теряем память между стеком и кучей:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Допустим, у кучи задачи А параметр base равен 126 Кб, а bounds — 2 Кб. Пусть задача А обращается к виртуальному адресу 3 Кб (в куче). Тогда физический адрес определяется как 3 – 2 Кб (начало кучи) = 1 Кб + 126 Кб (сдвиг) = 127 Кб. Это меньше 128, а значит ошибки обращения не будет.

Совместное использование сегментов

Сегментирование физической памяти не только не позволяет виртуальной памяти отъедать физическую, но также даёт возможность совместного использования физических сегментов с помощью виртуальных адресных пространств разных процессов.

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

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

При этом оба процесса не подозревают, что делят с кем-то свою память. Такой подход стал возможен благодаря внедрению битов защиты сегмента (segment protection bits).

Поскольку сам код нельзя модифицировать, то все кодовые сегменты создаются с флагами RX. Это значит, что процесс может загружать эту область памяти для последующего выполнения, но в неё никто не может записывать. Другие два сегмента — куча и стек — имеют флаги RW, то есть процесс может считывать и записывать в эти свои два сегмента, однако код из них выполнять нельзя. Это сделано для обеспечения безопасности, чтобы злоумышленник не мог повредить кучу или стек, внедрив в них свой код для получения root-прав. Так было не всегда, и для высокой эффективности этого решения требуется аппаратная поддержка. В процессорах Intel это называется “NX bit”.

Флаги могут быть изменены в процессе выполнения программы, для этого используется mprotect().

Под Linux все эти сегменты памяти можно посмотреть с помощью утилит /proc//maps или /usr/bin/pmap.

Здесь есть все необходимые подробности относительно распределения памяти. Адреса виртуальные, отображаются разрешения для каждой области памяти. Каждый совместно используемый объект (.so) размещён в адресном пространстве в виде нескольких частей (обычно код и данные). Кодовые сегменты являются исполняемыми и совместно используются в физической памяти всеми процессами, которые разместили подобный совместно используемый объект в своём адресном пространстве.

Shared Objects — это одно из крупнейших преимуществ Unix- и Linux-систем, обеспечивающее экономию памяти.

Также с помощью системного вызова mmap() можно создавать совместно используемую область, которая преобразуется в совместно используемый физический сегмент. Тогда у каждой области появится индекс s, означающий shared.

Ограничения сегментации

Итак, сегментация позволила решить проблему неиспользуемой виртуальной памяти. Если она не используется, то и не размещается в физической памяти благодаря использованию сегментов, соответствующих именно объёму используемой памяти.

Но это не совсем верно.

Допустим, процесс запросил у кучи 16 Кб. Скорее всего, ОС создаст в физической памяти сегмент соответствующего размера. Если пользователь потом освободит из них 2 Кб, тогда ОС придётся уменьшить размер сегмента до 14 Кб. Но вдруг потом программист запросит у кучи ещё 30 Кб? Тогда предыдущий сегмент нужно увеличить более чем в два раза, а возможно ли это будет сделать? Может быть, его уже окружают другие сегменты, не позволяющие ему увеличиться. Тогда ОС придётся искать свободное место на 30 Кб и перераспределять сегмент.

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

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

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

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

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

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

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

Разбиение памяти на страницы

Как было сказано выше, главный недостаток сегментации заключается в том, что сегменты очень часто меняют свой размер, и это приводит к фрагментации памяти, из-за чего может возникнуть ситуация, когда ОС не выделит для процессов нужные области памяти. Эта проблема решается с помощью страниц: каждое размещение, которое ядро делает в физической памяти, имеет фиксированный размер. То есть страницы — это области физической памяти фиксированного размера, ничего более. Это сильно облегчает задачу управления свободным объёмом и избавляет от фрагментации.

Давайте рассмотрим пример: виртуальное адресное пространство объёмом 16 Кб разбито на страницы.

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Мы не говорим здесь о куче, стеке или кодовом сегменте. Просто делим память на куски по 4 Кб. Затем то же самое делаем с физической памятью:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

ОС хранит таблицу страниц процесса (process page table), в которой представлены взаимосвязи между страницей виртуальной памяти процесса и страницей физической памяти (страничный кадр, page frame).

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Теперь мы избавились от проблемы поиска свободного места: страничный кадр либо используется, либо нет (unused). И ядру не в пример легче найти достаточное количество страниц, чтобы выполнить запрос процесса на выделение памяти.

Страница — это мельчайшая и неделимая единица памяти, которой может оперировать ОС.

У каждого процесса есть своя таблица страниц, в которой представлена переадресация. Здесь уже используются не значения границ области, а номер виртуальной страницы (VPN, virtual page number) и сдвиг (offset).

Пример: размер виртуального пространства 16 Кб, следовательно, нам нужно 14 бит для описания адресов (2 14 = 16 Кб). Размер страницы 4 Кб, значит нам нужно 4 Кб (16/4), чтобы выбрать нужную страницу:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Когда процесс хочет использовать, например, адрес 9438 (вне границ 16 384), то он запрашивает в двоичном коде 10.0100.1101.1110:

segmentation fault core dumped как исправить. Смотреть фото segmentation fault core dumped как исправить. Смотреть картинку segmentation fault core dumped как исправить. Картинка про segmentation fault core dumped как исправить. Фото segmentation fault core dumped как исправить

Это 1246-й байт в виртуальной странице номер 2 («0100.1101.1110»-й байт в «10»-й странице). Теперь ОС достаточно просто обратиться к таблице страниц процесса, чтобы найти эту страницу номер 2. В нашем примере она соответствует восьмитысячному байту физической памяти. Следовательно, виртуальный адрес 9438 соответствует физическому адресу 9442 (8000 + сдвиг 1246).

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

Если сами таблицы страниц хранятся в памяти, то для получения VPN надо обращаться к памяти. Тогда количество обращений к ней удваивается: сначала мы извлекаем из памяти номер нужной страницы, а затем обращаемся к самим данным, хранящимся в этой странице. И если скорость доступа к памяти невелика, то ситуация выглядит довольно грустно.

Буфер быстрой переадресации (TLB, Translation-lookaside Buffer)

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

Для поддержания производительности снова используется помощь оборудования. Как и при сегментации, мы аппаратными методами помогаем ядру эффективно осуществлять переадресацию. Для этого используется TLB, входящий в состав MMU, и представляющий собой простой кэш для некоторых VPN-переадресаций. TLB позволяет ОС не обращаться к памяти лишний раз, чтобы получить физический адрес из виртуального.

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

Как вы понимаете, если в кэше отсутствует нужная переадресация, то это замедляет обращение к памяти. Можно предположить, что чем больше размер страниц, тем больше вероятность, что в TLB окажутся нужные данные. Но тогда мы будем тратить больше памяти на каждую страницу. Так что здесь нужен какой-то компромисс. Современные ядра умеют использовать страницы разных размеров. Например, Linux способен оперировать «огромными» страницами по 2 Мб вместо традиционных 4 Кб.

Также рекомендуется хранить данные компактно, в смежных адресах памяти. Если вы раскидаете их по всей памяти, то куда чаще в TLB не будет обнаруживаться нужной переадресации, либо он будет постоянно переполняться. Это называется эффективностью пространственной локальности (spacial locality efficiency): данные, которые расположены в памяти сразу за вашими, могут размещаться в той же физической странице, и тогда благодаря TLB вы получите выигрыш в производительности.

Кроме того, TLB в каждой записи хранит так называемые ASID (Address Space Identifier, идентификатор адресного пространства). Это нечто вроде PID, идентификатора процесса. Каждый процесс, поставленный в очередь на выполнение, имеет собственный ASID, и TLB может управлять обращением любого процесса к памяти, без риска ошибочных обращений со стороны других процессов.

Повторимся снова: если пользовательский процесс пытается обратиться к неправильному адресу, тот наверняка будет отсутствовать в TLB. Следовательно, будет запущена процедура поиска в таблице страниц процесса. В ней хранится переадресация, но с неправильным набором битов. В х86-системах переадресации имеют размер 4 Кб, то есть битов в них немало. А значит есть вероятность найти правильный бит, равно как и другие вещи, наподобие бита изменения («грязного бита», dirty bit), битов защиты (protection bit), бита обращения (reference bit) и т.д. И если запись помечена как неправильная, то ОС по умолчанию выдаст SIGSEGV, что приведёт к ошибке “segmentation fault”, даже если о сегментах уже и речи не идёт.

На самом деле разбиение памяти на страницы в современных ОС устроено куда сложнее, чем я расписал. В частности, используются многоуровневые записи в таблицах страниц, многостраничные размеры, вытеснение страниц (page eviction), также известное как «обмен» (ядро скидывает страницы из памяти на диск и обратно, что повышает эффективность использования основной памяти и создаёт у процессов иллюзию её неограниченности).

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *