Проверьте параметры адреса на NULL или нет в publi c функциях - PullRequest
0 голосов
/ 28 февраля 2020

Я создаю свою функцию onw strlen, которая будет публичной c функцией и предназначена для x64 ...

Теперь у меня есть вопрос о передаче строкового адреса этой функции ... this Функция получает адрес строки, используя регистр RAX ... Теперь я хочу знать, действительно ли необходимо проверить, что указанный адрес равен NULL (0) или нет? потому что строковый адрес может быть любым, и даже если указанный адрес недействителен, произойдет cra sh! и в действительности нет необходимости делать это в верхней части функции:

test rax, rax        ; string-address == 0 (NULL) ?
jz   .ret0

, поэтому в publi c функциях действительно необходимо проверять предоставленный адрес, равен ли он 0? потому что я думаю, что это дополнительное действие !!!! (даже для publi c функций)

Ответы [ 2 ]

1 голос
/ 01 марта 2020

В ISO C вызов стандартной функции strlen с указателем NULL является неопределенным поведением. Это не требует / гарантии cra sh, это просто означает, что это возможно. (И демоны летят из твоего носа). UB означает буквально все, что может произойти (без нарушения стандарта).

Очевидно, что на практике набор вещей, которые могут на самом деле произойти, обычно не так велик, и, конечно, большинство ОС не делают этого. даже позволяет вам отобразить нулевую страницу на всех. (И большинство реализаций C / C ++ используют битовый шаблон 0 в качестве объектного представления для nullptr / NULL, так же, как исходный уровень C / C ++ 0, хотя забавный факт это не обязательно.)

Таким образом, большинство strlen-реализаций просто начинают с загрузки первого байта. (Или, если он не пересекает страницу, загрузите первые 16 байтов, чтобы без ветвей проверить на ноль с SSE2. Безопасно ли читать после конца буфера в пределах одной и той же страницы на x86 и x64? есть некоторые обсуждения реализаций glib c x86-64 asm strlen.)

Если вызывающий хочет избежать сбоя в указателях NULL, проверьте перед вызовом.

Это прекрасно действительно для написания функции без проверки nullptr, , пока эта часть контракта становится понятной для людей, пишущих код, который ее вызывает.

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

Кроме того, что вы могли бы вернуть, что будет полезным для вашего вызывающего абонента для Нулевой ввод? 0 подразумевает, что можно прочитать ptr[0] и найти '\0'. Может быть, это нормально для некоторых звонящих. size_t - это тип без знака, поэтому любое другое возможное значение является положительным, а также допустимым размером.

1 голос
/ 28 февраля 2020

Это зависит от того, что ваша функция должна делать:

Во многих API передача указателя NULL должна иметь определенный эффект. Например, вы sh сообщаете, что ваша функция возвращает -1, если передан указатель NULL.

В этом случае вы должны добавить эту проверку.

Возможно, вы запустите свою программу в операционной системе, где адрес 0 является действительным адресом. (Это не тот случай, когда используются современные ОС, но в старых (1996) Linux версиях это могло бы быть так.)

В этом случае ваша реализация strlen() также будет работать, если первый символ строки хранится по адресу 0.

Это означает, что вы должны не добавить эту проверку в этом случае.

...