Есть ли безопасный способ утверждать, если строковое представление завершается нулем? - PullRequest
2 голосов
/ 14 октября 2019

У меня есть часть в коде, которая широко использует представление строк. Было бы немыслимо использовать std::string везде, и char const* не будет работать, так как есть ассоциативные контейнеры, множество сравнений и такие операции, которые трудно выполнить с простыми необработанными строками.

Однако естьместо, которое в конечном итоге будет иметь дело с C API, и ему нужны строки с нулевым символом в конце:

auto sv = std::string_view{/* ... */};
c_api(sv.data());

Хотя в моем случае это работает нормально, я хотел бы убедиться, что все в порядке, и утверждать, что строкитеряют значение null, так как моя система, создающая строковые представления и отправляющая туда, не будет использовать подстроки и будет либо создавать их из строковых литералов, либо std::string. Я знаю, что со мной все будет в порядке.

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

Поэтому я хотел сообщить об этом, используя assert:

auto sv = std::string_view{/* ... */};
assert(*(sv.data() + sv.length()) == '\0'); // Yay?
c_api(sv.data());

Но я нахожу его неполным и подверженным ошибкам, поскольку он может читатьвне границы строки с нулевым символом в конце.

Есть ли способ безопасно утверждать, что строковое представление действительно завершено нулем?

1 Ответ

2 голосов
/ 14 октября 2019

Это может быть больно, но я бы написал свой собственный string_view, который гарантированно обнуляется.

Так как string_view может быть построен как

char array[3] = {'B', 'a', 'r'};
std::string_view array_v(array, sizeof array);

test

*(sv.data() + sv.length()) == '\0'

- это неопределенное поведение в этом случае, так как последний действительный индекс равен 2, ноВы получаете доступ 3. std::string_view потребуется раскрыть информацию, которую он не может знать, чтобы вы могли это сделать, а поскольку это невозможно, вы не можете достоверно знать.

...