Segmentation fault on nullptr check when incrementing the ptr to iterate over an array

59 views Asked by At

The following code, when compiled and run gives a segmentation fault. I was trying out the sample on page 12 of a Tour of C++ on a MacBook.

compilation command - clang++ -Wall -std=c++11 -o replacement.o replacement.cpp && ./replacement.o

Error message - 'zsh: segmentation fault ./replacement.o'

Full code -

#include <iostream>

int count_occurances(char* p, char x)
{
    int count = 0;
    // count number of times x occurs in p
    while (p != nullptr)
    {
        if (*p == x)
            ++count;
        ++p;
    }
    return count;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    char num_array[4] = {'a', 'b', 'b', 'c'};
    std::cout << "Running count occurances array" << count_occurances(num_array, 'b') << "done\n" ;
    return 0;
}

Essentially tried to iterate over the array by incrementing the pointer but somehow messing up the nullptr check, as a result it's accessing memory it shouldn't.

2

There are 2 answers

0
iammilind On BEST ANSWER

This is because p != nullptr is always true as p = &num_array which is a valid address.
The nullptr comparison should be at the beginning of the function as a general sanity check.

Continuing ++p beyond the sizeof(num_array) = 4, it's an undefined behaviour. In your system it crashes with a segmentation fault.

Either you pass the sizeof(num_array) as a function parameter OR assign 0 (NUL) character at the end:

char num_array[] = {'a', 'b', 'b', 'c', 0};

Then the loop should be while(*p != 0).

0
Dražen Grašovec On

You probably wanted to check for NULL terminator at the end of the C string But char array declared and initialized in this way is not NULL terminated

char num_array[4] = {'a', 'b', 'b', 'c'};

If you want to declare a NULL terminated C style string you can use this way with string literal:

char num_array[5] = {"abbc"};

And as stated in answer above, pointer p is just an address of the array (or the address of an element of array) If you want to get or set the value pointer points to, you have to dereference it:

*p or *(p + index)

But accessing elements out of array boundary leads to UB and can crash your program.