У чому полягає помилка сегментації? Чи відрізняється він у С та С ++? Як пов’язані помилки сегментації та звисаючі покажчики?
NullPointerException
.
У чому полягає помилка сегментації? Чи відрізняється він у С та С ++? Як пов’язані помилки сегментації та звисаючі покажчики?
NullPointerException
.
Відповіді:
Помилка сегментації - це специфічна помилка, викликана доступом до пам'яті, яка "не належить вам". Це допоміжний механізм, який запобігає пошкодженню пам’яті та впровадженню важких помилок пам’яті. Щоразу, коли ви отримуєте сегментарне меню, ви знаєте, що ви робите щось не так з пам'яттю - доступ до змінної, яка вже звільнилася, запис у частину пам'яті, лише для читання, і т.д. в управлінні пам'яттю немає принципової різниці між сегментами segfault в C і C ++.
Існує багато способів отримати сегментарій, принаймні, на мовах нижчого рівня, таких як C (++). Поширений спосіб отримати сегментарний стандарт - це знецінення нульового вказівника:
int *p = NULL;
*p = 1;
Ще один сегмент за замовчуванням відбувається, коли ви намагаєтесь записати на частину пам'яті, яка була позначена як лише для читання:
char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault
Висячий покажчик вказує на те, що вже не існує, як тут:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
Вказівник p
звисає, оскільки він вказує на змінну символів, c
яка припинила своє існування після закінчення блоку. І коли ви спробуєте знеструмити висячий покажчик (як *p='A'
), ви, ймовірно, отримаєте сегмент за замовчуванням.
c
це локально, це означає, що його було натиснуто на стек після {
і вискочив з нього після }
. звисаючий покажчик - це лише посилання на зміщення, яке зараз поза стеком. ось чому зміна його у простій програмі ніколи не запускає жодних segfault. з іншого боку, це може призвести до segfault у складнішому випадку використання, коли інші виклики функцій можуть привести стек до зростання та містити дані, на які вказує звисаючий покажчик. Запис на ці дані (місцеві варси) призведе до невизначеної поведінки (segfault & Co)
SIGSEGV
, тому я не очікую, що такий сигнал буде керуватися стеком.
Варто зазначити, що помилка сегментації не викликана прямим доступом до іншої пам'яті процесу (це те, що я чую іноді), оскільки це просто неможливо. У віртуальній пам'яті кожен процес має власний віртуальний адресний простір, і немає жодного способу отримати доступ до іншого, використовуючи будь-яке значення вказівника. Винятком з цього можуть бути спільні бібліотеки, які є однаковим фізичним адресним простором, відображеним на (можливо) різні віртуальні адреси та пам'ять ядра, яка навіть відображається однаково у кожному процесі (я думаю, щоб уникнути TLB промивання на syscall, я думаю). І такі речі, як shmat;) - це те, що я вважаю "непрямим" доступом. Однак можна перевірити, що вони зазвичай розташовані далеко від коду процесу, і ми зазвичай маємо доступ до них (саме тому вони там,
Тим не менш, помилка сегментації може статися в разі неправильного доступу до власної (технологічної) пам’яті (наприклад, спроби запису в неписаний простір). Але найпоширенішою причиною цього є доступ до тієї частини віртуального адресного простору, яка зовсім не відображається на фізичну.
І все це стосовно систем віртуальної пам'яті.
Помилка сегментації викликається запитом на сторінку, яку процес не вказав у своїй таблиці дескрипторів, або недійсним запитом для тієї сторінки, яку вона перелічила (наприклад, запит на запит на сторінці лише для читання).
Висячий покажчик - це вказівник, який може або не може вказувати на дійсну сторінку, але вказує на "несподіваний" сегмент пам'яті.
Якщо чесно, як згадували інші афіші, у Вікіпедії є дуже гарна стаття з цього приводу, тож подивіться там. Цей тип помилок дуже поширений і його часто називають іншими речами, такими як Порушення доступу або Помилка загального захисту.
Вони не відрізняються C, C ++ або будь-якою іншою мовою, яка дозволяє вказувати. Ці помилки, як правило, викликаються вказівниками, які є
За вікіпедією:
Помилка сегментації виникає, коли програма намагається отримати доступ до місця пам'яті, до якого не дозволено, або намагається отримати доступ до місця пам'яті способом, який не дозволений (наприклад, спроба запису в місце, доступне лише для читання, або перезаписати частину операційної системи).
Помилка сегментації також спричинена збоями в апаратному забезпеченні, в цьому випадку - оперативною пам'яттю. Це менш поширена причина, але якщо ви не знайдете помилки у своєму коді, можливо, повідомлення може допомогти вам.
Рішенням в цьому випадку є зміна ОЗУ.
редагувати:
Тут є посилання: Помилка сегментації апаратними засобами
Помилка сегментації виникає, коли процес (запущений екземпляр програми) намагається отримати доступ до адреси пам'яті лише для читання або діапазону пам'яті, який використовується іншим процесом, або отримати доступ до неіснуючої (недійсної) адреси пам'яті. Проблема Dangling Reference (pointer) означає, що намагаються отримати доступ до об'єкта чи змінної, вміст якої вже видалено із пам'яті, наприклад:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
Сторінка Segmentation_fault у Вікіпедії має дуже приємний опис про неї, лише вказуючи на причини та причини. Загляньте у вікі для детального опису.
При обчисленні помилка сегментації (часто скорочена до сегмента) або порушення доступу - це помилка, яка виникає за допомогою апаратного забезпечення із захистом пам’яті, повідомляючи операційну систему (ОС) про порушення доступу до пам'яті.
Нижче наведено кілька типових причин помилки сегментації:
Вони, в свою чергу, часто викликані помилками програмування, які призводять до недійсного доступу до пам'яті:
Перенаправлення або присвоєння неініціалізованому покажчику (дикий покажчик, який вказує на випадкову адресу пам'яті)
Перенаправлення або присвоєння звільненому вказівнику (звисаючий вказівник, який вказує на пам'ять, яку було звільнено / розібрано / видалено)
Переповнення буфера.
Переповнення стека.
Спроба виконати програму, яка не компілюється правильно. (Деякі компілятори будуть видавати виконуваний файл, незважаючи на наявність помилок часу компіляції.)
Простими словами: помилка сегментації - це операційна система, що надсилає сигнал програмі, вказуючи, що вона виявила незаконне доступ до пам'яті і передчасно припиняє програму, щоб запобігти пошкодженню пам'яті.
"Помилка сегментації" означає, що ви намагалися отримати доступ до пам'яті, до якої ви не маєте доступу.
Перша проблема - ваші основні аргументи. Основна функція повинна бути int main(int argc, char *argv[])
, і ви повинні перевірити, чи є arc принаймні 2, перш ніж звертатися до argv [1].
Крім того, оскільки ви переходите поплавком до printf (який, до речі, при переході до printf перетворюється в подвійний), вам слід використовувати специфікатор формату% f. Специфікатор формату% s призначений для рядків (масиви символів, що закінчуються '\ 0').
Помилка сегментації або порушення доступу виникає, коли програма намагається отримати доступ до місця пам'яті, яке не існує, або намагається отримати доступ до місця пам'яті у спосіб, який заборонено.
/* "Array out of bounds" error
valid indices for array foo
are 0, 1, ... 999 */
int foo[1000];
for (int i = 0; i <= 1000 ; i++)
foo[i] = i;
Тут я [1000] не існує, тому відбувається segfault.
Причини сегментації:
it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.
De-referencing NULL pointers – this is special-cased by memory management hardware.
Attempting to access a nonexistent memory address (outside process’s address space).
Attempting to access memory the program does not have rights to (such as kernel structures in process context).
Attempting to write read-only memory (such as code segment).
У відповідях є кілька хороших пояснень "помилки сегментації", але оскільки при помилках сегментації часто виникає дамп вмісту пам'яті, я хотів поділитися тим, де взаємозв'язок між "ядрою, демпінгованою" частиною, у розбитті сегментації (ядро скинуто) та пам'ять походить від:
Приблизно з 1955 по 1975 рік - до напівпровідникової пам'яті - домінуючої технології в пам'яті комп'ютера використовували крихітні магнітні пончики, нанизані на мідні дроти. Пончики були відомі як "феритові ядра" і основна пам'ять, таким чином, відома як "основна пам'ять" або "серцевина".
Взято звідси .
Визначень несправності сегментації досить, я хотів би навести кілька прикладів, на які я зіткнувся під час програмування, які можуть здатися дурними помилками, але витрачатимуть багато часу.
ви можете отримати помилку сегментації у нижньому випадку, тоді як аргумент невідповідності типу printf
#include<stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
вихід: Segmentation Fault (SIGSEGV)
коли ви забули виділити пам'ять вказівнику, але намагаєтесь її використовувати.
#include<stdio.h>
typedef struct{
int a;
}myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
вихід: Segmentation Fault (SIGSEGV)
Просте значення Segmentation fault
полягає в тому, що ви намагаєтеся отримати доступ до деякої пам'яті, яка вам не належить. Segmentation fault
виникає, коли ми намагаємося читати та / або писати завдання в пам'яті, лише для читання, або намагаємось звільнити пам'ять. Іншими словами, ми можемо пояснити це як якесь пошкодження пам’яті.
Нижче я згадую про поширені помилки, які роблять програмісти Segmentation fault
.
scanf()
неправильно (забув поставити &
).int num;
scanf("%d", num);// must use &num instead of num
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
printf()
та scanf()
'