Наскільки небезпечним є доступ до масиву поза межами?


221

Наскільки небезпечним є доступ до масиву поза його межами (в С)? Іноді може траплятися, що я читаю з-за масиву (тепер я розумію, що потім отримую доступ до пам’яті, яка використовується в деяких інших частинах моєї програми або навіть поза цим) або намагаюся встановити значення індексу поза масивом. Програма іноді виходить з ладу, але іноді просто працює, даючи лише несподівані результати.

Тепер, що я хотів би знати, наскільки це насправді небезпечно? Якщо це шкодить моїй програмі, це не так вже й погано. Якщо, з іншого боку, щось зламає поза моєю програмою, тому що я якось встиг отримати доступ до якоїсь абсолютно не пов'язаної пам’яті, я думаю, це дуже погано. Я читав багато "все, що може статися", "сегментація може бути найменш поганою проблемою" , "ваш жорсткий диск може стати рожевим, і єдинороги можуть співати під вашим вікном", що все приємно, але яка насправді небезпека?

Мої запитання:

  1. Чи може зчитування значень із шляху поза масивом пошкоджувати щось, крім моєї програми? Я б міг уявити, що дивлячись на речі нічого не змінюється, чи це, наприклад, змінить атрибут "в останній раз відкритий" файлу, до якого я потрапив?
  2. Чи може встановлення значень, що виходять за межі масиву, пошкодити щось, крім моєї програми? З цього питання щодо переповнення стека я розумію, що можна отримати доступ до будь-якого місця пам'яті, що немає гарантії безпеки.
  3. Зараз я запускаю свої невеликі програми зсередини XCode. Чи забезпечує це додатковий захист навколо моєї програми, коли вона не може вийти за межі власної пам'яті? Чи може це нашкодити XCode?
  4. Будь-які рекомендації щодо безпечного запуску коду помилки?

Я використовую OSX 10.7, Xcode 4.6.


Загалом, ОС захистить себе та інші процеси від вашої ненависті. Однак це не те, на що ти хочеш сильно покластися.
Гарячі лизання

7
Крім того, вам ніколи не траплятиметься "файл" на вашому жорсткому диску, коли ви отримуєте доступ та масив індекс поза межами (у вашому барі).
БарабанчикB

1
я вважаю, ви запитуєте про масив C, правда? так що це не має нічого спільного з ObjC і насправді не стосується жодної IDE.
Брайан Чен

17
Ось мій улюблений приклад дивних результатів (він стосується стека, але я вважав, що це дійсно освіжаюче ...).
phipsgabler

Відповіді:


125

Що стосується стандарту ISO C (офіційне визначення мови), то доступ до масиву поза його межами має " невизначене поведінку ". Буквальний сенс цього полягає в:

поведінка при використанні неподатної або помилкової конструкції програми або помилкових даних, до яких цей Міжнародний стандарт не пред'являє жодних вимог

На це поширюється ненормативна примітка:

Можлива невизначена поведінка варіюється від ігнорування ситуації повністю з непередбачуваними результатами, до поведінки під час перекладу чи виконання програми в документально підтвердженому для середовища середовищі (з видачею діагностичного повідомлення або без нього), до припинення перекладу чи виконання (з видачею діагностичного повідомлення).

Так це теорія. Яка реальність?

У кращому випадку ви отримаєте доступ до частини пам'яті, яка або належить вашій поточній програмі (що може спричинити неправильну поведінку вашої програми), або не належить вашій запущеній програмі (що, ймовірно, спричинить вашу програму збої з чимось на зразок помилки сегментації). Або ви можете спробувати записати в пам'ять, якою володіє ваша програма, але це позначено лише для читання; це, ймовірно, також призведе до збою вашої програми.

Це припустимо, що ваша програма працює в операційній системі, яка намагається захистити одночасно запущені процеси один від одного. Якщо ваш код працює на «голому металі», скажіть, якщо він є частиною ядра ОС або вбудованої системи, то такого захисту немає; ваш недобросовісний код - це те, що повинно було забезпечити цей захист. У цьому випадку можливості пошкодження значно більше, включаючи, в деяких випадках, фізичне пошкодження обладнання (або речей або людей, які знаходяться поблизу).

Навіть у захищеному середовищі ОС захист не завжди є 100%. Існують помилки в операційній системі, які дозволяють, наприклад, непривілейованим програмам отримувати кореневий (адміністративний) доступ. Навіть із звичайними привілеями користувача, несправна програма може споживати зайві ресурси (процесор, пам'ять, диск), можливо, знищуючи всю систему. Багато шкідливих програм (вірусів тощо) використовує надмірну кількість буферів для отримання несанкціонованого доступу до системи.

(Один історичний приклад: я чув, що в деяких старих системах з основною пам'яттю багаторазовий доступ до одного місця пам’яті в тісному циклі може буквально спричинити плавлення цієї пам’яті. Інші можливості включають знищення дисплея CRT та переміщення прочитаного / запишіть голову дисковода з гармонійною частотою шафи накопичувача, змусивши його пройти по столу і впасти на підлогу.)

І завжди існує хвилювання Skynet .

Суть полягає в наступному: якщо ви могли б написати програму , щоб зробити що - то погане свідомо , це по крайней мере , теоретично можливо , що глючить програма може робити те ж саме випадково .

На практиці, це дуже малоймовірно , що ваш баггі програма працює на системі MacOS X збирається зробити що - небудь серйозніше , ніж аварії. Але повністю запобігти помилковому коду неможливо зробити дійсно погані речі.


1
дякую, я насправді цілком розумію це. Але це негайно викликає подальше запитання: що може зробити початківець програміст, щоб захистити свій комп’ютер від власних, можливо, жахливих творінь? Після того, як я ретельно випробував програму, я можу розкрити її у світі. Але перший пробний цикл повинен бути неправильною програмою. Як ви, хлопці, захищаєте свої системи від себе?
ChrisD

6
@ChrisD: Ми, як правило, пощастили. 8-)} Серйозно, захист на рівні ОС досить хороший в наші дні. Найгірший випадок, якщо я напишу випадкову вилкову бомбу , мені, можливо, доведеться перезавантажитись для відновлення. Але справжній збиток для системи, мабуть, не варто турбувати, якщо ваша програма не намагається зробити щось на межі небезпеки. Якщо ви дійсно переживаєте, запуск програми на віртуальній машині може бути не поганою ідеєю.
Кіт Томпсон

1
З іншого боку, я бачив, як багато дивних речей трапляється на комп'ютерах, які я використовував (пошкоджені файли, непоправні системні помилки тощо), і я не маю уявлення, скільки з них могло бути викликано деякою програмою на C жахлива невизначена поведінка. (Поки жоден власний демон не вилетів з мого носа.)
Кіт Томпсон,

1
дякую за те, що ви навчали мене бомбовиками - я зробив речі, близькі до цього, коли намагався зрозуміти рекурсію :)
ChrisD

2
scienceamerican.com/article/… тому в сучасній електроніці все ще можливий вогонь.
Mooing Duck

25

Загалом, сьогоднішні операційні системи (популярні в будь-якому випадку) запускають усі програми в захищених регіонах пам'яті за допомогою віртуального менеджера пам'яті. Виявляється, не просто ЛЕГКО (за скажімо) просто читати або записувати до місця, яке існує в РЕАЛЬНОМУ просторі за межами регіону, який був призначений / виділений для вашого процесу.

Прямі відповіді:

1) Читання майже ніколи не завдає шкоди іншому процесу, однак це може побічно пошкодити процес, якщо трапиться прочитати значення KEY, яке використовується для шифрування, дешифрування або перевірки програми / процесу. Читання поза межами може вплинути на ваш код дещо негативно / несподівано, якщо ви приймаєте рішення на основі даних, які читаєте

2) Єдиний спосіб, коли ви могли дійсно ПІДТВОРИТИ щось, записуючи на адресу, доступну за адресою пам’яті, якщо ця адреса пам’яті, до якої ви пишете, - це фактично апаратний реєстр (місце, яке насправді не для зберігання даних, а для керування частиною) апаратного забезпечення) не місце оперативної пам'яті. Насправді, ви все одно звичайно не пошкоджуєте щось, якщо не пишете якесь програмоване одноразове місце, яке не підлягає повторному запису (або щось подібне).

3) Зазвичай, що працює всередині налагоджувача, запускає код у режимі налагодження. Запуск у режимі налагодження ТЕНДУЄ (але не завжди) швидше зупиняти ваш код, коли ви зробили щось, що вважається поза практикою або прямо незаконним.

4) Ніколи не використовуйте макроси, використовуйте структури даних, у яких вже вбудовані межі індексу масиву тощо.

ДОДАТКОВО Додам, що вищенаведена інформація справді лише для систем, що використовують операційну систему з вікнами захисту пам'яті. Якщо ви пишете код для вбудованої системи або навіть системи, що використовує операційну систему (в режимі реального часу чи іншу), яка не має вікон захисту пам’яті (або віртуальних адресованих вікон), слід бути набагато обережнішим у читанні та записі в пам'ять. Також у цих випадках завжди слід застосовувати безпечні та безпечні методи кодування, щоб уникнути проблем із безпекою.


4
Завжди слід застосовувати безпечні та безпечні практики кодування .
Nik Bougalis

3
Я б запропонував НЕ використовувати try / catch для баггі-коду, якщо ви не виберете дуже конкретні винятки і не знаєте, як відновити їх. Catch (...) - це найгірше, що ви можете додати до помилкового коду.
Євген

1
@NikBougalis - Я повністю погоджуюся, але це ВЖЕ ВАЖЛИВО, якщо ОС не включає захист пам’яті / віртуальний адресний простір, або ОС бракує :-)
труби

@Eugene - Я ніколи не помічав, що це проблема для мене, але я згоден з вами, чи я це відредагував :-)
труби

1) ви маєте на увазі шкоду, тому що я розкривав би щось, що повинно було залишитися в таємниці? 2) Я не впевнений, що я розумію, що ви маєте на увазі, але я думаю, що я отримую доступ до оперативної пам’яті лише намагаючись отримати доступ до місць поза межами масиву?
ChrisD

9

Якщо не перевіряти межі, це може призвести до неприємних побічних ефектів, включаючи безпеку. Одне з негарних - це довільне виконання коду . У класичному прикладі: якщо у вас є масив фіксованого розміру, і ви використовуєте strcpy()для того, щоб помістити туди надану користувачем рядок, користувач може надати вам рядок, що переповнює буфер і перезаписує інші місця пам'яті, включаючи кодову адресу, куди повинен повернутися процесор, коли ваша функція закінчення.

Це означає, що ваш користувач може надіслати вам рядок, який призведе до того, що ваша програма по суті буде дзвонити exec("/bin/sh"), що перетворить її в оболонку, виконуючи все, що він хоче у вашій системі, включаючи збирання всіх ваших даних та перетворення машини на ботнет-вузол.

Докладніше про те, як це можна зробити, перегляньте розділ « Розбиття стека для розваги та прибутку» .


Я знаю, що мені не слід отримувати доступ до елементів масиву поза межами меж, дякую за посилення цієї точки. Але питання полягає в тому, що, окрім завдавання всілякої шкоди моїй програмі, чи можу я ненароком вийти за межі пам'яті своєї програми? І я маю на увазі на OSX.
ChrisD

@ChrisD: OS X - це сучасна операційна система, тому вона забезпечить вам повний захист пам’яті. Наприклад, ви не повинні обмежуватися тим, що ваша програма може робити. Це не повинно включати возитися з іншими процесами (якщо ви не працюєте під root правами).
че

Я вважаю за краще привілеї ring 0, а не root.
Руслан

Більш цікавим є те , що гіпер-сучасний компілятор може прийняти рішення про те , що якщо код намагається читати foo[0]через foo[len-1]після того , як раніше використовував перевірку в lenвідношенні довжини масиву або виконати або пропустити фрагмент коду, компілятор повинен відчувати себе вільно працювати , що інший код беззастережно навіть якби програма володіє сховищем минулого масиву, а наслідки його читання були б доброякісними, але ефекту виклику іншого коду не було б.
supercat

8

Ви пишете:

Я читав багато "все, що може статися", "сегментація може бути найменш поганою проблемою", "ваш жорсткий диск може стати рожевим, і єдинороги можуть співати під вашим вікном", що все приємно, але яка насправді небезпека?

Давайте так сказати: завантажте пістолет. Направляйте його за вікном без особливої ​​мети та вогню. Яка небезпека?

Питання в тому, що ви не знаєте. Якщо ваш код перезаписать щось, що збиває вашу програму, ви все в порядку, оскільки це зупинить його у визначеному стані. Однак якщо вона не виходить з ладу, проблеми починають виникати. Які ресурси перебувають під контролем вашої програми і що це може зробити для них? Які ресурси можуть потрапити під контроль вашої програми і що це може зробити для них? Я знаю принаймні одне головне питання, яке було викликане таким переповненням. Проблема полягала в начебто безглуздій статистичній функції, яка заплутала деяку незв’язану таблицю перетворення для виробничої бази даних. Результатом цього стало дуже дороге прибирання. Насправді було б набагато дешевше і простіше впоратися, якби ця проблема відформатувала жорсткі диски ... іншими словами: рожеві єдинороги можуть бути вашою найменшою проблемою.

Ідея, що ваша операційна система захистить вас, є оптимістичною. По можливості намагайтеся уникати виписування за межі.


ок, саме цього я боявся. Я намагатимусь уникати виписування меж, але, бачачи те, що я робив останні кілька місяців, я, безумовно, ще багато цього роблю. Як ви, хлопці, настільки добре пограбували в програмуванні без безпечного способу занять?
ChrisD

3
Хто сказав, що будь-що було безпечно;)
Удо Кляйн

7

Якщо ваша програма не працює як root або будь-який інший привілейований користувач, це не завдасть шкоди жодній вашій системі, тому, як правило, це може бути хорошою ідеєю.

Записуючи дані в якесь місце випадкової пам'яті, ви безпосередньо не «пошкодите» будь-яку іншу програму, що працює на вашому комп’ютері, оскільки кожен процес працює у власному просторі пам’яті.

Якщо ви спробуєте отримати доступ до будь-якої пам'яті, не виділеної вашому процесу, операційна система зупинить виконання вашої програми з помилкою сегментації.

Тож безпосередньо (без запуску root та прямого доступу до таких файлів, як / dev / mem) немає небезпеки, що ваша програма буде перешкоджати будь-якій іншій програмі, що працює у вашій операційній системі.

Тим не менш - і, напевно, про це ви чули з точки зору небезпеки - сліпо записуючи випадкові дані у випадкові місця пам'яті випадково, ви впевнені, що ви можете пошкодити все, що ви можете пошкодити.

Наприклад, ваша програма може захотіти видалити певний файл, заданий ім'ям файлу, який зберігається десь у вашій програмі. Якщо ви випадково просто перезаписали місце, де зберігається ім'я файлу, ви можете замість цього видалити зовсім інший файл.


1
Якщо будуть запущені як корінь (або яким - або іншим привілейованим користувач), хоча, стережіться. Перевищення розмірів буфера та масиву - це звичайне використання зловмисних програм.
Джон Боде

насправді обліковий запис, який я використовую для своїх щоденних обчислень, не є обліковим записом адміністратора (я використовую термінологію OSX, оскільки це моя система). Ви хочете сказати мені, що я не можу щось пошкодити, намагаючись встановити будь-яке місце пам'яті? Це насправді чудова новина!
ChrisD

Як уже згадувалося раніше, найгірша шкода, яку ви можете заподіяти випадково - це найгірша шкода, яку ви можете зробити як користувач. Якщо ви хочете бути на 100% впевнені, що не знищите жодної своєї інформації, можливо, ви можете додати інший обліковий запис на свій комп'ютер і експериментувати з цим.
mikyra

1
@mikyra: Це справедливо лише в тому випадку, якщо захисні механізми системи на 100% ефективні. Наявність шкідливого програмного забезпечення говорить про те, що на це не завжди можна покластися. (Я не хочу припускати, що про це обов'язково варто потурбуватися; можливо, але малоймовірно, що програма може випадково використати ті самі отвори в безпеці, якими експлуатується зловмисне програмне забезпечення.)
Кіт Томпсон,

1
Список тут включає: Запуск коду з ненадійних джерел. Просто натисніть кнопку ОК на будь-якому спливаючому екрані брандмауера, навіть не читаючи, про що йдеться, або повністю відключити його, якщо потрібне мережеве з'єднання неможливо встановити. Виправлення бінарних файлів найновішим хаком із сумнівних джерел. Це не вина у сховищі, якщо власник буде добровільно запросити будь-якого грабіжника з обома руками та надзвичайно міцними укріпленими дверима, широко відкритими.
mikyra

4

NSArrays в Objective-C призначається певний блок пам'яті. Перевищення меж масиву означає, що ви отримаєте доступ до пам'яті, яка не призначена для масиву. Це означає:

  1. Ця пам'ять може мати будь-яке значення. Неможливо дізнатися, чи є дані дійсними на основі вашого типу даних.
  2. Ця пам'ять може містити конфіденційну інформацію, таку як приватні ключі або інші облікові дані користувачів.
  3. Адреса пам'яті може бути недійсною або захищеною.
  4. Пам'ять може мати змінне значення, оскільки до неї звертається інша програма або потік.
  5. Інші речі використовують адресний простір пам’яті, наприклад, порти, зіставлені з пам’яттю.
  6. Запис даних на невідому адресу пам’яті може призвести до збою вашої програми, перезапису пам’яті операційної пам’яті та, як правило, спричиняє випадання сонця.

З точки зору програми ви завжди хочете знати, коли ваш код перевищує межі масиву. Це може призвести до повернення невідомих значень, що призведе до збою вашої програми або надання недійсних даних.


NSArraysмають поза межами винятків. І це питання, мабуть, стосується масиву C.
БарабанчикB

Я дійсно мав на увазі масиви С. Я знаю, що є NSArray, але наразі більшість моїх вправ є в С
КріСД,

4

Можливо, ви захочете спробувати скористатися memcheckінструментом у Valgrind під час тестування свого коду - він не сприймає порушення окремих меж масиву в межах кадру стека, але він повинен вирішити безліч інших проблем із пам’яттю, включаючи ті, які можуть спричинити тонкі, ширші проблеми, що виходять за межі однієї функції.

З посібника:

Memcheck - детектор помилок пам'яті. Він може виявити такі проблеми, які є загальними для програм C і C ++.

  • Доступ до пам’яті ви не повинні, наприклад, розгортання та заниження блоків купи, перевищення вершини стека та доступ до пам’яті після її звільнення.
  • Використання невизначених значень, тобто значень, які не були ініціалізовані, або які були отримані з інших неозначених значень.
  • Неправильне звільнення пам'яті купи, наприклад, подвійне звільнення блоків купи, або невідповідне використання malloc / new / new [] проти безкоштовного / видалення / видалення []
  • Перекриття покажчиків src та dst у memcpy та пов'язаних з ними функціях.
  • Пам'ять протікає.

ETA: Хоча, як говорить відповідь Каза, це не панацея і не завжди дає найбільш корисний результат, особливо коли ви використовуєте захоплюючі схеми доступу.


Я б підозрював, що аналізатор XCode знайде більшу частину цього? і моє питання не стільки в тому, як знайти ці помилки, але якщо виконання програми, в якій все ще є ці помилки, небезпечно для пам'яті, не виділеної для моєї програми. Мені доведеться виконати програму, щоб побачити помилки, які відбуваються
ChrisD

3

Якщо ви коли-небудь займаєтесь програмуванням на рівні систем або програмованими вбудованими системами, дуже погані речі можуть трапитися, якщо ви запишете у випадкові місця пам'яті. Старіші системи та багато мікроконтролерів використовують IO, відображений на пам'яті, тому записування до місця пам'яті, яке відображається в периферійний регістр, може спричинити загрозу, особливо якщо це робиться асинхронно.

Приклад - програмування флеш-пам’яті. Режим програмування на мікросхемах пам'яті вмикається шляхом запису певної послідовності значень у конкретні місця у межах адресного діапазону чіпа. Якщо інший процес повинен був записувати в будь-яке інше місце в мікросхемі, поки це тривало, це призведе до збою циклу програмування.

У деяких випадках апаратне забезпечення обертає адреси навколо (більшість значущих біт / байт адреси ігнорується), тому записування на адресу поза межами фізичного адресного простору насправді призведе до того, що дані записуються прямо посередині.

І нарешті, більш старі процесори, такі як MC68000, можуть заблокуватись до того моменту, що лише апаратне скидання може змусити їх знову працювати. Не працював над ними пару десятиліть, але я вважаю, що коли виникає помилка в шині (неіснуюча пам'ять) при спробі обробляти виняток, вона просто зупиниться, доки не буде затверджено скидання обладнання.

Моя найбільша рекомендація - це кричущий штекер для продукту, але я не маю особистого інтересу до нього, і я жодним чином не пов'язаний з ними - але на основі декількох десятиліть програмування С та вбудованих систем, де надійність була критичною, ПК Gimpel Лінт не тільки виявить подібні помилки, він зробить з вас кращого програміста C / C ++, постійно натягуючи на вас про шкідливі звички.

Я також рекомендую ознайомитися зі стандартом кодування MISRA C, якщо ви можете комусь скопіювати копію. Я не бачив жодних останніх, але в старі дні вони дали хороше пояснення, чому ви повинні / не повинні робити те, що вони охоплюють.

Давно про вас, але про 2-й або 3-й раз, коли я отримую коридору або зависання від будь-якої програми, моя думка про те, що компанія виробляла, знижується вдвічі. Четвертий або п'ятий раз, і все, що пакет є, стає посудом, і я проїжджаю дерев’яну колу через центр пакету / диска, він прийшов, щоб переконатися, що він ніколи не повертається до мене.


Залежно від системи, зчитування поза діапазоном може також викликати непередбачувану поведінку, або вони можуть бути доброякісними, хоча доброякісна поведінка обладнання на навантаженні поза діапазону не передбачає доброякісної поведінки компілятора.
supercat

2

Я працюю з компілятором для мікросхеми DSP, який свідомо генерує код, який отримує доступ один минулий кінець масиву з коду C, який не робить!

Це відбувається тому, що петлі побудовані так, що кінець ітерації попередньо вибирає деякі дані для наступної ітерації. Таким чином, попередньо встановлена ​​дата в кінці останньої ітерації ніколи фактично не використовується.

Написання подібного коду С посилається на невизначене поведінку, але це лише формальність із стандартного документа, що стосується максимальної переносимості.

Частіше, ні, програма, яка отримує доступ за межі, не є розумно оптимізованою. Це просто баггі. Код отримує деяке значення сміття, і, на відміну від оптимізованих циклів вищезгаданого компілятора, код потім використовує значення в наступних обчисленнях, тим самим пошкоджуючи їх.

Варто ловити помилки таким чином, і тому варто зробити поведінку невизначеною навіть тільки з цієї причини: щоб час запуску міг створити діагностичне повідомлення типу "перевищення масиву в рядку 42 main.c".

У системах з віртуальною пам’яттю може виникнути розподіл масиву таким чином, що наступна адреса знаходиться у незробленій області віртуальної пам’яті. Після цього доступ буде бомбити програму.

Зауважте, що в C нам дозволено створити вказівник, який знаходиться в кінці масиву. І цей покажчик повинен порівняти більше, ніж будь-який вказівник, на внутрішній масив. Це означає, що реалізація C не може розмістити масив прямо в кінці пам'яті, де адреса один плюс обернеться і буде виглядати менше, ніж інші адреси в масиві.

Тим не менш, доступ до неініціалізованих значень або за межами меж іноді є дійсною методикою оптимізації, навіть якщо не є максимально портативною. Це, наприклад, чому інструмент Valgrind не повідомляє про доступ до неініціалізованих даних, коли ці звернення трапляються, але лише тоді, коли значення пізніше використовується якимось чином, що може вплинути на результат програми. Ви отримуєте діагностику на кшталт "умовна гілка в xxx: nnn залежить від неініціалізованого значення", і іноді важко відстежити, звідки вона походить. Якби всі подібні звернення були негайно захоплені, було б багато помилкових позитивних результатів, що випливають з коду, оптимізованого компілятором, а також правильно оптимізованого кодом.

Якщо говорити про це, я працював з деяким кодеком від постачальника, який видав ці помилки під час перенесення в Linux та запуску під Valgrind. Але продавець переконав мене, що лише кілька бітвикористовуваного значення насправді походить з неініціалізованої пам'яті, і ці біти ретельно уникали логіки. Використовувалися лише хороші біти значення, і Valgrind не має можливості відстежувати окремий біт. Неініціалізований матеріал з’явився з прочитанням слова в кінці бітового потоку кодованих даних, але код знає, скільки бітів у потоці і не використовуватиме більше бітів, ніж насправді є. Оскільки доступ за межі кінця масиву бітових потоків не завдає ніякої шкоди архітектурі DSP (немає ні віртуальної пам’яті після масиву, ні портів, відображених у пам’яті, а адреса не обертається), це правильна техніка оптимізації.

"Не визначена поведінка" насправді не означає багато, тому що згідно з ISO C, просто включення заголовка, який не визначений у стандарті C, або виклик функції, яка не визначена в самій програмі або стандарті C, є прикладами невизначених поведінка. Невизначена поведінка не означає "не визначена ніким на планеті", просто "не визначена стандартом ISO C". Але, звичайно ж , іноді невизначений поведінка дійсно є абсолютно не визначений ніким.


Крім того, за умови існування щонайменше однієї програми, яку певна реалізація правильно обробляє, хоча вона номінально оподатковує всі обмеження на реалізацію, наведені в Стандарті, ця реалізація може поводитись довільно, коли подається на будь-яку іншу програму, яка не має обмежень у порушеннях і все ще є " поступливий ". Отже, 99,999% програм C (що завгодно, крім «однієї програми» платформи) покладаються на поведінку, коли Стандарт не пред'являє жодних вимог.
supercat

1

Окрім власної програми, я не думаю, що ви нічого не зламаєте, в гіршому випадку ви спробуєте прочитати чи записати з адреси пам'яті, що відповідає сторінці, яку ядро ​​не призначило вашим процесам, створивши належне виключення і будучи вбитим (я маю на увазі ваш процес).


3
..Що? Як щодо перезапису пам’яті у вашому власному процесі, який використовується для зберігання змінної, використаної пізніше ... яка тепер загадково змінила своє значення! Запевняю, ці помилки - це безліч задоволень. Найвищий результат - найкращий результат. -1
Ред С.

2
Я маю на увазі, що він не «порушить» інші процеси, окрім власної програми;)
jbgs

Мені справді все одно, якщо я порушую власну програму. Я просто навчаюсь, програма явно все-таки помиляється, якщо я отримую доступ до чогось поза межами мого масиву. Я просто все більше переживаю ризики зламати щось інше під час налагодження своїх творінь
ChrisD

Річ у тім: чи можу я бути впевненим, якщо спробую отримати доступ до пам'яті, не призначеної мені, що мій процес буде вбитий? (перебуває на OSX)
ChrisD

3
Роки тому я був незграбним програмістом на С. Я звертався до масивів поза їх межами сотні разів. Крім того, що мій процес був убитий операційною системою, ніколи нічого не сталося.
jbgs
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.