Коли і чому покажчики почали сприйматись як ризиковані?


18

Схоже, відбувся поступовий зсув у мисленні щодо використання покажчиків у мовах програмування, так що стало загальноприйнятим, що покажчики вважаються ризикованими (якщо не відвертими «злими» чи подібними посиленнями).

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

Наприклад, поверхневий огляд назад при переході від C до C ++ до Java, схоже, демонструє тенденцію до доповнення, а потім повністю заміни покажчиків на посилання. Однак реальна ланцюжок подій була, ймовірно, набагато більш тонка і складна, ніж ця, і не настільки настільки послідовна. Особливості, які перетворили його на ці основні мови, можливо, виникли в інших місцях, можливо, задовго до цього.

Примітка. Я не запитую про фактичні достоїнства покажчиків проти посилань порівняно з чимось іншим. Моя увага зосереджена на обґрунтуванні цього очевидного зрушення.


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

10
Покажчики є ризикованими. Чому, на вашу думку, відбувся зсув у мисленні? Були вдосконалені мовні функції та апаратні засоби, які дозволяють писати програмне забезпечення без покажчиків, хоча не без певної міри покарання.
Перестаньте шкодити Моніці

4
@DaveInCaz Наскільки я знаю, конкретна розробка була винаходом покажчиків.
Перестаньте шкодити Моніці

5
@nocomprende: те, що ви тільки що написали, - це не факти чи докази, а лише думка. У 1970 році було набагато менше програмістів, ви не маєте жодних доказів, що населення сьогодні є «кращим чи гіршим» при «непрямому посиланні».
whatsisname

3
Покажчики завжди вважалися ризикованими з першого дня. Це було просто компромісом, щоб перенести їх з монтажу на мови вищого рівня.
Френк Хілеман

Відповіді:


21

Обґрунтуванням було розробка альтернативи покажчикам.

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

Це завжди було "небезпечно", але небезпека відносна. Коли ви робите програму на 1000 ліній або коли у вас є процедури якості програмного забезпечення для IBM, ця небезпека може бути легко усунена. Однак не все програмне забезпечення розроблялося саме так. Як таке виникло прагнення до більш простих структур.

Якщо ви задумаєтесь, то int&і int* constсправді такий же рівень безпеки, але один має симпатичніший синтаксис, ніж інший. int&також може бути більш ефективним, оскільки він може посилатися на int, що зберігається в реєстрі (анахронізм: це було і раніше, але сучасні компілятори настільки хороші в оптимізації, що ви можете мати вказівник на ціле число в реєстрі, якщо ви ніколи не використовуєте жодну з функцій, для яких потрібна фактична адреса, наприклад ++)

Коли ми переходимо на Java , ми переходимо на мови, які надають певні гарантії безпеки. C і C ++ не надавали жодного. Java гарантує виконання лише юридичних операцій. Для цього java повністю усунула покажчики. Вони виявили, що переважна більшість операцій з вказівками / довідками, виконаними в реальному коді, були речами, для яких посилання були більш ніж достатніми. Лише у кількох випадках (наприклад, швидка ітерація через масив) вказівники були справді потрібні. У цих випадках java вживає час виконання, щоб уникнути їх використання.

Цей крок не був одноманітним. C # знову введені покажчики, хоча у дуже обмеженій формі. Вони позначені як " небезпечні ", тобто не можуть бути використані ненадійним кодом. Вони також мають чіткі правила щодо того, на що вони можуть, а на що не можуть вказувати (наприклад, збільшувати покажчик повз кінець масиву просто недійсно ). Однак вони виявили, що було кілька випадків, коли потрібні були високі показники покажчиків, тому вони повертають їх назад.

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


3
Я не впевнений, що правильно сказати, що у Java немає покажчиків. Я не хочу вступати в довгі дебати про те, що є, а не є вказівником, але JLS говорить, що "значення посилання є вказівником". Просто не допускається прямий доступ чи зміна покажчиків. Це стосується не лише безпеки, тому що GC не допомагає людині відслідковувати, де об’єкт знаходиться в будь-який момент, корисно.
JimmyJames

6
@JimmyJames Правда. Для цілей цієї відповіді розділовою лінією між покажчиком та не-покажчиком було те, чи підтримує він арифметичні операції вказівника, які зазвичай не підтримуються посиланнями.
Корт Аммон - Відновити Моніку

8
@JimmyJames Я погоджуюся з твердженням Корта, що вказівник - це те, на чому можна робити арифметичні операції, тоді як посилання - ні. Фактичний механізм, який реалізує посилання на таких мовах, як Java, - це деталь реалізації.
Роберт Харві

3
Загалом, C і C ++ добровільно прийняли членство в цьому небезпечному клубі, ввівши багато специфікацій в специфікацію.
rwong

2
До речі, є в ЦПУ, який відрізняє між покажчиками і числами. Наприклад, оригінальний 48-розрядний процесор CISC в IBM AS / 400 робить це. І справді, є рівень абстракції під ОС, що означає , що не тільки центральний процесор розрізняти між числами і покажчиками і упаси арифметика покажчиків, але сама ОС не навіть не знає про покажчики на всі і не займайтеся мови . Цікаво, що це робить оригінальну систему AS / 400 єдиної системи, де перезапис коду з мови скриптів високого рівня в C робить його на порядок повільнішим .
Йорг W Міттаг

10

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

Більшість мов програмування високого рівня (тобто не Асамблея) досить безпечні для пам’яті і забороняють необмежений доступ вказівника. Сімейство С тут є дивним.

С розвинувся з B, що було дуже тонкою абстракцією над сирим складом. Б мав один тип: слово. Слово може використовуватися як ціле число або як вказівник. Ці два еквівалентні, коли вся пам'ять розглядається як єдиний суміжний масив. C зберігав цей досить гнучкий підхід і продовжував підтримувати за своєю суттю небезпечну арифметику вказівника. Вся система типу С є більш задумливою. Ця гнучкість доступу до пам'яті зробила C дуже придатним для його основного призначення: прототипування операційної системи Unix. Звичайно, Unix і C виявилися досить популярними, так що C використовується також у додатках, де цей підхід до низької пам’яті насправді не потрібен.

Якщо ми подивимось на мови програмування, що виходили до C (наприклад, діалекти Fortran, Algol, включаючи Pascal, Cobol, Lisp,…), деякі з них підтримують C-подібні покажчики. Зокрема, концепція нульових покажчиків була винайдена для Algol W в 1965 році. Але жодна з цих мов не намагалася бути мовою C-подібних, ефективних систем з низькою абстракцією: Fortran призначений для наукових обчислень, Algol розробив деякі досить передові концепції, Lisp - це більше науково-дослідного проекту, ніж мови галузевого рівня, і Кобол був зосереджений на бізнес-додатках.

Збір сміття існував з кінця 50-х років, тобто задовго до С (на початку 70-х). Для належної роботи GC вимагає безпека пам'яті. Мови до і після С використовували GC як звичайну функцію. Звичайно, це робить мову набагато складнішою та, можливо, повільнішою, що було особливо помітно під час мейнфреймів. Мови GC, як правило, орієнтовані на дослідження (наприклад, Lisp, Simula, ML) та / або потребують потужних робочих станцій (наприклад, Smalltalk).

З меншими, більш потужними комп’ютерами, що обчислюють загалом, а мови GC, зокрема, стали більш популярними. Для додатків у реальному часі (а іноді навіть тоді) GC є кращим підходом. Але алгоритми ГК також були предметом інтенсивних досліджень. Як альтернатива, покращена безпека пам’яті без GC також була розвинута в подальшому, особливо за останні три десятиліття: помітними нововведеннями є RAII та розумні покажчики в системі C ++ та система перевірки / запозичення життя Руста.

Java не впроваджувала інновацій, будучи безпечною для пам'яті мовою програмування: вона в основному прийняла семантику мови GCed, безпечної для пам'яті мови Smalltalk та поєднала їх із синтаксисом та статичним типізацією C ++. Потім вона була продана як краща, простіша C / C ++. Але це лише поверхово нащадок C ++. Відсутність покажчиків Java завдячує набагато більшою мірою об'єктній моделі Smalltalk, ніж відмови від моделі даних C ++.

Тому "сучасні" мови, такі як Java, Ruby та C #, не слід трактувати як подолання проблем сировинних покажчиків, як у C, але їх слід розглядати як черпання з багатьох традицій - включаючи C, а також із більш безпечних мов, таких як Smalltalk, Simula, або Лісп.


4

На мій досвід, покажчики ЗАВЖДИ були складною концепцією для багатьох людей. У 1970 році університет, який я відвідував, мав Burroughs B5500, і ми використовували Extended Algol для наших програм програмування. Архітектура апаратури базувалася на дескрипторах та деяких кодах у верхній частині слів даних. Вони були чітко розроблені, щоб дозволити масивам використовувати покажчики, не дозволяючи їм ходити з кінця.

У нас відбувалися жваві дискусії в класі про те, як посилатися на ім’я та значення та про те, як працювали масиви B5500. Деякі з нас отримали пояснення негайно. Інші - ні.

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

Багато людей, з якими я працював, почали писати FORTRAN, потім перейшли до C, написали C, що дуже схоже на FORTRAN, і уникали покажчиків. Оскільки вони ніколи не інтерналізуються вказівниками та посиланнями, Java створює проблеми. Часто для програмістів FORTRAN складно зрозуміти, як дійсно працює призначення об’єктів.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.