Comments (13)
Hi @jonnygrant,
There are some compile-time checks that are offered by GSL not_null, such as disallowing construction directly from the nullptr (i.e., f(nullptr);
), but these are implemented via C++ language features (such as deleting the constructor taking std::nullptr_t
). Otherwise, all checks intentionally occur at runtime.
More comprehensive compile-time checks would be best achieved via a static analysis tool that understands gsl::not_null
. For example MSVC currently has some experimental gsl::not_null support that would raise a compile-time diagnostic on your code example.
from gsl.
@jonnygrant thanks for continuing the investigation and iterating on the design.
With your latest changes, this example fails to compile: https://godbolt.org/z/o6oj63Pd1, whereas in the existing GSL implementation it will compile and run fine if the pointer is not null, and runtime error otherwise.
int main()
{
gsl::not_null<int*> test = new (std::nothrow) int();
int a = *test;
(void)a; // suppress unused var warning
}
In fact, even the following code will fail the compile-time check:
https://godbolt.org/z/4TG1aP3os
void foo(int* ptr)
{
gsl::not_null<int*> nn = ptr; // compiler can't assert that ptr != nullptr, compile_error_null_check
(void)nn; // suppress unused var warning
}
int main() {}
So the programming model effectively proposed with these changes requires the users of not_null
to manually insert nullchecks:
void foo(int* ptr)
{
if (ptr == nullptr) return;
gsl::not_null<int*> nn = ptr; // compiles fine
(void)nn; // suppress unused var warning
}
int main() {}
If this is intended, then you will probably want to first open a CoreGuidelines issue to discuss this proposal, since it is a non-trivial deviation from the current programming model suggested by not_null
.
from gsl.
@dmitrykobets-msft Many thanks for your reply and the suggestion, I've filed on CppCoreGuidelines now. Let's see what they say.
You're right nullptr checks would need to be inserted in some application code.
My idea gives the programmer chance to evaluate where the nullptr came from at build time, and what logic caused it.
from gsl.
I tried
strict_not_null
but it also didn't give what I need.
https://godbolt.org/z/nET6nse31
from gsl.
I tried
strict_not_null
but it also didn't give what I need. https://godbolt.org/z/nET6nse31
That is expected. The difference between strict_not_null
and not_null
is that strict_not_null
has an explicit
constructor whereas not_null
has a constructor that can be called implicitely. And that difference is not relevant for what you want to achieve.
from gsl.
Hi @dmitrykobets-msft Many thanks for your reply.
Thank you for the static analysis tool suggestion. It's a good idea. I'm only on GNU/Linux gcc, so I don' think I could compile that unfortunately.
I did patch not_null locally, and now the build stops in an optimized build when it sees my int* is NULL
Example uses the following. It adds a dummy method, just to trigger the warning -Wnotnull
__attribute__ ((nonnull));
https://godbolt.org/z/xd1YeE5cs
Would you consider integrating something similar into the official GSL not_null class?
from gsl.
This might be better using
__attribute__((error("not_null found nullptr")));
https://godbolt.org/z/cMvjqb93T
Could you consider adding this. It works with GCC and Clang.
from gsl.
In your godbolt with error
I changed the definition of test
in main
to int * test = new (std::nothrow) int();
. That code still does not compile because the pointer might be null and the compiler might need to call compile_error_null_check
. So with this proposed solution legitimate code does not compile.
from gsl.
I tried your suggestion with GCC and found the same, however with clang, it did compile
https://godbolt.org/z/63jYWW794
Same with malloc(8), clang compiled but not gcc.
https://godbolt.org/z/hve7hha9x
Maybe the
__attribute__ ((nonnull));
example is better I provided above.
from gsl.
Your __attribute__((nonnull))
change also fails with GCC and int * test = new (std::nothrow) int();
.
from gsl.
Your
__attribute__((nonnull))
change also fails with GCC andint * test = new (std::nothrow) int();
.
May I ask, my idea is to get a not_null build error when a pointer is passed that might be nullptr. So it seems to be working as expected?
You get a nice compile time error when accidentally passing a value that might be a nullptr as a not_null<int*>
In constructor 'constexpr gsl::not_null<T>::not_null(T) [with <template-parameter-2-1> = void; T = int*]',
inlined from 'int main()' at <source>:475:6:
<source>:236:53: error: argument 1 null where non-null expected [-Werror=nonnull]
For such a fatal memory allocation failure by new, I'd put some handler in to log it and abort()
if(nullptr == test)
{
log_error("FATAL new (std::nothrow) int(); returned nullptr\n");
abort();
}
Oddly this attribute nonnull example doesn't work in the else {}, even after checking the pointer is valid. Sharing the link
https://godbolt.org/z/7661ffdxK
from gsl.
In your godbolt with
error
I changed the definition oftest
inmain
toint * test = new (std::nothrow) int();
. That code still does not compile because the pointer might be null and the compiler might need to callcompile_error_null_check
. So with this proposed solution legitimate code does not compile.
I updated this error
example after getting the build error for the possible nullptr returned by operator new, so this works well
https://godbolt.org/z/Kh6Wa3oTM
from gsl.
Maintainers call: Closed per isocpp/CppCoreGuidelines#2071
from gsl.
Related Issues (20)
- ❓ Please take the GSL GitHub survey HOT 1
- Question: How to print a gsl::byte? HOT 2
- How to use the smartpointer overloads inside `<span_ext>`? HOT 1
- Purpose of `<span_ext>`
- Provide a "safe" and "simple" way for binary I/O HOT 2
- Type mismatch in span::operator[] HOT 4
- gsl.pc and gsl/gsl_rng.h files not found HOT 2
- CMake Error at CMakeLists.txt:14 (find_package): Could not find a package configuration file provided by "Microsoft.GSL" HOT 2
- Missing `swap` for `gsl::not_null` for move-only types HOT 4
- `GSL_SUPPRESS(y)` expands to `[[gsl::suppress("x")]]` for clang HOT 5
- Can not build with gcc13 because suggestion warning HOT 3
- gsl::not_null and std::variant are not fully compatible
- Reproducible build? HOT 2
- [Help] About the signed copy of my CLA HOT 1
- C++20 Modules Support? HOT 3
- how to do bound check for vector::front and vector::back HOT 2
- MSVC: Recent commits break compilation
- Turning off clang unsafe buffer warnings fails when compiling with a gcc based compiler HOT 2
- When will a new version be released? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gsl.