cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

Добавить в язык подержку nullability #522

Open klappdev opened 2 years ago

klappdev commented 2 years ago

Неотъемлемой частью языка являются указатели. Использование указателей несет некоторые проблемы, в частности: разименование нулевого указателя, работа с нулевым указателями ссылающиеся на поля объекта, и т.д. Как результат имеем segmentation fault, и долгие часы дебага.

   int* ptr = nullptr;
   int a = *ptr;                      //  segmentation fault

Поэтому всегда нужно проверять, является указатель нулевым или нет.

Часто программисты из-за невнимательности или сложной логики кода, могут не все случаи проверить валидности указателей. Как замена указателям в С++, имеются ссылки, умные указатели. Но иногда без указателей не обойтись, например использование С-библиотек, new/delete и т.д.

В Clang попытались решить проблему с указателями, добавив ключевые слова _Nonnull, _Nullable. Атрибуты nullability позволяют статическому анализатору подсказывать, где указатель используется некорректно.

int function(_Nonnull int* ptr) {
     int a = *ptr;                        // warning
}

Но что если в проекте не используется статический анализатор кода, или Clang компилятор. То потенциальные ошибки останутся в коде. Что не очень хорошо.

Еще одним решение является реализовать оберточки над указателя - non_null, nullable. Если указатель, в какой-то момент не валидный, то можно бросить исключения. И в нас уже есть замечательная библиотека gsl.

int function(gsl::non_null<int*> ptr) {
     int a = *ptr;                        // throw exception
}

Но почему в библитеке нет gsl::nullable. И еще как минус нельзя расширить обработчик ошибок. Например, если в проекте используется Java/C++, то хотелось кидать java-исключения с нативным стектрейсом. https://github.com/klappdev/firearrow/blob/master/app/src/main/cpp/util/nullability/NonNull.hpp https://github.com/klappdev/firearrow/blob/master/app/src/main/cpp/util/nullability/Nullable.hpp

Предлагаю добавить два класса в стандартную библиотеку - std::non_null<T>, std::nullable<T>. Если указатель, в какой-то момент не валидный, то можно бросить исключения.

int function(std::non_null<int*> ptr) {
     int a = *ptr;                        // throw exception
}

int function(std::nullable<int*> ptr) {
    if (ptr != nullptr) { 
         int a = *ptr;                        // ok
    }
}

Также добавить функцию std::set_nullability(). Для того, чтобы можно переопределить дефолтное поведения. По аналогии с функцией - std::terminate.

Очень хочется видеть подобные оберточки в С++.

Полезные ссылки:

kelbon commented 2 years ago

Как замена указателям в С++, имеются ссылки, умные указатели.

Это не замена указателям. В современном С++ это всё разные семантики:

Поэтому потенциальный std::nullable уже есть в языке и называется T*, а std::non_null называется T&

P.S. not_null\<T> это T, nullable\<T> это optional\<T> в более общем случае

incoder1 commented 1 year ago

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

int* p;
...
*p = 1;
int *p = new int;
delete p;
...
delete p;
#include <thread>

int main(int argc, const char** argv) {
  int *p = new int;
  std::thread t0( [p] { *p = 1; } );
  std::thread t1( [p] { *p = 2; } );
  std::thread t2( [p] { *p = 3 ;} );
  delete p;
}
void foo(int* p) 
{
  if(nullptr != p)
    delete p;
}

int main(int argc, const char** argv) 
{
  int i = 1;
  foo(&i);
  return 0;
}

Это все никак не решить без статического анализа и рантайм анализа либо дополнительной программми типа СppCheck, Valgrind и т.п. или внесением этих интсрументов в компилятор и среду, по типу Rust.

Умные указатели и стратегия подсчета ссылок уже давно решает часть проблем, но далеко не все. Монады типа std::optional тоже не панация.

apolukhin commented 1 year ago

Есть у меня идейка, займусь статическим анализом и жёстким и гарантиями на владение