7

After some change of the code-base I came accross this gotcha:

#include <string>

void test(const std::string& s){
}

int main()
{
    test(NULL);
    return 0;
}

https://godbolt.org/z/7uJnef

This throws an exception. Changing to 'nullptr' helps nothing (still no error or warning).

I guess my question is, is there a way to detect or find this error at pre-runtime throughout the sourcecode ? perhaps some compiler warning, etc. (using MSVC VS-2017)

I ended up modifying the basic_string template ala. basic_string(int) = delete; basic_string(::std::nullptr_t) = delete; - this won't catch all cases but does indeed seem to catch the direct cases at least

4
  • 4
    This is a job for a static analyzer. std::string has a cont char* converting constructor so you can't stop it from accepting a null pointer. Commented Oct 9, 2019 at 12:25
  • @NathanOliver exactly (Im painfully aware of that) - do you think cpp core check can help here ? Commented Oct 9, 2019 at 12:26
  • 1
    I would hope so. They should be able to detect the null pointer dereference. Commented Oct 9, 2019 at 12:29
  • Accept nullptr or not is a pre-condition question. Commented Oct 9, 2019 at 15:00

3 Answers 3

4

Running cppcheck (version 1.89) on the example file yields:

Checking test.cpp ...
test.cpp:9:10: error: Null pointer dereference [nullPointer]
test(NULL);
     ^
Sign up to request clarification or add additional context in comments.

7 Comments

I will try that
Last time I've checked cppcheck it suffered from lack of proper C++11 support and complained about syntax errors everywhere. Did they fix this and even implement support for C++17 in recent releases?
@VTT I think they try to be roughly up to date (no idea w.r.t C++17, but the C++11 basics should be fine), but I guess manually specifying which tests to run might be the way to go.
It seems VS2017 cpp core check is not able to detect this one
@lubgr I tried to give cppcheck a spin - what options are you using exactly ? at first it doesn't find this error - checking includes it tells me it cannot find <string> header but tells me this isn't an issue...
|
3

You can add a couple of prohibited overloads capturing use of 0, NULL or nullptr arguments:

void test(int bad_argument) = delete;
void test(::std::nullptr_t bad_argument) = delete;

4 Comments

If we just could add this to std::string itself- then it would be great !
You need an overload for void test(const char*) as well (and have it call test("") if null), otherwise the caller can do something like const char *s = nullptr; test(s); and still crash at runtime.
@RemyLebeau thats a good point - I am less worried about that situation at the time being though
I ended up modifying the basic_string template ala. ` basic_string(int) = delete; basic_string(::std::nullptr_t) = delete;` - this ofc. won't catch all cases but does indeed seem to catch the direct cases at least
2

You can add a trampoline function that checks for NULL pointer at compile (and run) time, if your compiler supports it. For GCC it would look like this:

void test(const std::string& s){

}

void test(const char* ptr  __attribute__((nonnull))) {
    test(std::string(ptr));
}

int main()
{
    test(NULL);
    return 0;
}

The warning you get is:

<source>:13:14: warning: null passed to a callee that requires a non-null argument [-Wnonnull]

    test(NULL);
         ~~~~^

1 Comment

Even without compile-time checking for null, you should still use a trampoline, it can do something like this to ensure no exception is thrown on a null pointer: void test(const char* ptr) { if (!ptr) ptr = ""; test(std::string(ptr)); } or void test(const char* ptr) { test(std::string(ptr ? ptr : "")); }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.