Что такое безопасность типов и каковы “безопасные с точки зрения типов” альтернативы? [дубликат]

20
задан Community 23 May 2017 в 11:54
поделиться

10 ответов

Безопасность типа означает, что компилятор поможет проверить, что вы не смешиваете (несовместимые) типы данных.

Например, когда вы звоните memcpy , функция (и компилятор) видит только два указателя в памяти, и будет счастливо начнет копирование данных. Это означает, что вы можете смешивать несовместимые типы данных, такие как это:

SomeClass a;
AnotherClass b;
memcpy((void*)&a, (void*)&b, sizeof(b));

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

Поскольку вы уже используете векторы от STL, вы уже используете более или менее безопасную реализацию типа.

11
ответ дан 29 November 2019 в 23:14
поделиться

Краткая версия ответа:

class Person;

person.DoSomething(); // This is type safe.

void * p = &person; // You can now start doing unsafe things with p.

Вы не можете передать человека на мемкпи. Он только знает и заботится о памяти. Байты.

0
ответ дан 29 November 2019 в 23:14
поделиться

Безопасность типов регулирует использование компилятора, проверяющего, является ли переменная правильным типом. C очень слабо влияет на безопасность типов данных, например, в стандартах ANSI C, где указано, что продвижение типа происходит для типа данных char, пример в этом присваивании объясняет это,

char ch = 32; /* that is a space character accordingly to ASCII */
int n = ch + 3;

Заметьте, как переменная ch получает 'продвижение' к типу int. Это законно, но требует более тщательного изучения, если вы на это намекаете.

Компиляторы, такие как компилятор Си#, не допустят этого, именно поэтому в Си используется оператор приведения, например:

int n = (int)3.1415926535f;

Nit picky в сторону, т.е. значение pi, что происходит, так это то, что значение n будет 3.

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

Безопасность типа в современных языках более строгая, например, Java, C#, чтобы ограничить использование и значение переменных. PHP является отличным примером свободного набора текста, где вы можете сделать это:

$myvar = 34;
$myvar = $myvar + "foo";

является $myvar целым числом, или это плавающая точка, или это строка. Безопасность типов здесь не очень понятна, что является намерением, которое может привести к ошибкам и счастливой отладочной сессии, пытающейся выяснить, что происходит.

Надеюсь, это поможет

8
ответ дан 29 November 2019 в 23:14
поделиться

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

В случаях, о которых вы говорите, memcpy() и printf(), отсутствие безопасности типов связано с тем, как функции обрабатывают свои аргументы. Например, с помощью memcpy(arg1, arg2, len) байты len, начинающиеся по адресу памяти arg2, будут скопированы по адресу памяти arg1, независимо от того, на сколько байт arg1 указывает, потенциально перезаписывая другие части вашей программы.

Для поиска безопасных для типа альтернатив обратитесь к конструкторам и cout .

На самом деле, загляните во весь C++ FAQ Lite

1
ответ дан 29 November 2019 в 23:14
поделиться

«Безопасность типа» означает, что компилятор проверяет, что вы делаете правильные вещи с правильными типами (например, запускает ошибку компилятора, если вы пытаетесь лечить банан как оранжевый или дать строка в функцию, ожидаемую выводить целое число).

Тип Безопасность (в основном) идет прямо из окна, когда void * входит в картинку - это указатель, который может указывать на что-либо (полностью не знает о типовых), а языковые листья Собираясь с ним полностью в программистах руки (например, void * не в основном хороши для чего угодно, кроме как для того, чтобы быть обратно к исходному типу; это может представлять что-нибудь, но вы должны знать, что Это прежде чем вы можете использовать его).

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

Безопасная альтернатива типа MeMcpy (для массивов и контейнеров) может быть STD :: Copy в - это может быть реализовано в терминах MemMove, если все вовлечены типы Удовлетворяйте определенные требования, в противном случае он выполняет задания - с некоторыми классами вы можете сломать определенные инварианты, если вы обходите их общедоступный интерфейс и просто переходите и перемещаете / скопируете их в память (например, я полагаю, любой класс с нетривиальным конструктором копирования Собираюсь повзглянуться, если вы сделаете копии из него с мемкпином).

Тип-безопасная альтернатива в процедурах ввода-вывода C ввода / вывода - это ioStreams (и если вы хотите преимущества строки формата, Boost :: Format ).

1
ответ дан 29 November 2019 в 23:14
поделиться

Безопасность типа относится к парадигме кодирования, которая заставляет каждую переменную иметь выделенный тип во время компиляции, например int a = 4; double d = 100.0; struct ms {char s;} mystruct; Тип переменной никогда не 'теряется'. Если вы хотите изменить ее тип с a на b, то должно быть определено явное или неявное приведение.

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

float f = 1.f;
printf("This is a float: %f\nAnd this is a string: %s",f,f);

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

0
ответ дан 29 November 2019 в 23:14
поделиться

Это означает, что компилятор не выдаст предупреждение, если вы попытаетесь использовать тип таким образом, что для этого типа нет смысла. Например, следующее является неопределенным поведением и на практике будет копировать биты указателя в биты флота, где они не имеют никакого смысла. Если sizeof(char*) > sizeof(float), то он перезапишет все места памяти, которые окажутся чуть выше, чем f.

float f;
char *c = someString();
memcpy(&f, &c, sizeof(char*));
1
ответ дан 29 November 2019 в 23:14
поделиться

Подпись функции MEMCPY IS

void *memcpy (void* destination, const void* source, size_t num);

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

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

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

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

void* malloc (size_t size);

, поэтому, когда вы хотите выделить указатель на , например, поплавки , например, вы делаете:

float* ptr = (float*)malloc(sizeof(float*)*COUNT);

Вы вынуждены бросить Результат функции float * * В противном случае TypeCheck найдет присвоение Void * на поплавок * , но void * ] слишком общий, чтобы быть назначенным так: Тип проверки не удалось!

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

0
ответ дан 29 November 2019 в 23:14
поделиться

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

  • никогда не скрывают отслеживание стека; никогда не используйте "Перебросок", если в целях безопасности вы не хотите скрыть то, что произошло.
  • не чувствуют, что вам нужна обработка ошибок везде. По умолчанию, в ваших нижних ярусах, позволяя фактической ошибке проникнуть до верхнего ряда не плохо. UI/Контроллер - то, где необходимо действительно решить, как реагировать на что-то идущее не так, как надо.
  • В каждой точке, как самостоятельно, что точно вы хотите произойти, если что-то идет не так, как надо. Часто, вы не сможете думать о чем-либо лучше, чем просто позволить ему подойти к верхнему слою или даже к клиентской машине. (хотя в производственном повороте подробного создания отчетов.), Если это верно, просто позвольте ему пойти.
  • Удостоверяются, что вы избавляетесь от неуправляемых ресурсов (Что-либо, что реализует IDisposable.) Ваш доступ к данным является ярким примером. Любой ( А ) Вызов .Dispose () для вашего (особенно) соединение, команда, datareader и т.д. в Наконец блок, или ( B) используют Используя Синтаксис/Образец , который удостоверяется, что надлежащее Расположение происходит.
  • Ищут места, где ошибки вероятны и где можно искать определенные ошибки, реагировать (путем повторения, ожидания второго повторения, попытки того действия другой путь, и т.д.) и затем надо надеяться, успешно выполниться. Большая часть вашей обработки исключений должна заставить успех произойти, не только сообщить об отказах хорошо.
  • В слое данных, необходимо рассмотреть, что сделать, если что-то идет не так, как надо посреди многоступенчатого процесса. Можно позволить фактической ошибке проникнуть, но этот уровень должен дескриптор, убирающий вещи после ошибки. Вы будете иногда хотеть использовать транзакции.
  • В асинхронной ситуации (также (A). из-за нескольких потоков или (B). потому что бизнес-логика является процессами отдельно на "машинах задачи" и такой и реагировавший позже), у вас в особенности должен быть план относительно входа ошибок.
  • я видел бы "код обработки ошибок" в 25% вашего приложения, чем 100%. 100% означают, что вы, вероятно, хотели, это к стилю как вы имеет обработку ошибок.25% означает, что вы потратили время на обработку исключений там, где они действительно нуждались в обработке.
-121--3978040-

Безопасность типа означает, что компилятор может проверить, используются ли нужные типы. Например, если вы используете printf , вы можете случайно запустить программу, написав следующее:

printf("The meaning of life is %s", 42);

, потому что 42 является целым числом, а не последовательность.

27
ответ дан 29 November 2019 в 23:14
поделиться

Так как вы в любом случае были в Википедии: Тип безопасности .

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

MEMCPY не является безопасным в типе, потому что вы можете легко скопировать память о некоторых INT в массив CHAR и в конечном итоге с бессмысленными данными. PrintF не является безопасным типом, потому что вы можете предоставить спецификатор формата % I со строкой; Опять же, строка будет интерпретироваться как INT , и вы получите мусор. (Кстати, компилятор VC ++ проверяет строку формата в некоторых ситуациях.)

STD :: Vector является типовым безопасным, потому что он только позволяет устанавливать значения Данный тип T в него. (Конечно, вы можете сделать явные типовые погрузчики, но в том, что вы должны быть явным о том, чтобы делать что-то, что не типа безопасным).

2
ответ дан 29 November 2019 в 23:14
поделиться