2

I'm trying to replicate the linspace functions from Matlab and numpy (python) in C however, I keep getting the warning about dereferencing NULL pointer.

I'm very much a novice at C and having only worked in Matlab, python and lua before, pointers are quite something to try and wrap my head around!

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

 double* linspace(double init, double fin, int N) {
     double *x;
     int i = 0;
     double step = (fin - init) / (double)N;
     x = (double*)calloc(N, sizeof(double));

     x[i] = init; /*<=== Line 14*/

     for (i = 1; i < N; i++) {
         x[i] = x[i - 1] + step;
     }
     x[N - 1] = fin;
     return x;
}

int main() {
    double *x_array = linspace(0, 10, 1000);

    printf(&x_array);

    free(x_array);
    return 0;
}

And I get the exact warning:

Warning C6011   Dereferencing NULL pointer 'x'. Line 14

Obviously I'm sure its just a rookie mistake but I'm unsure of how to sort it!

Thanks.

SamuraiMelon
  • 297
  • 3
  • 11
  • 2
    You can't call `printf` like that. C doesn't have high-level print statements like Python. If you want to print the array, use a loop. Or craeet an array-printing function with a loop. (But the compiler really should have warned you. The first argument to `printf` is nearly always a string literal.) – M Oehm Mar 15 '20 at 16:50
  • 1
    Well if the problem is indeed with this line `x[i] = init;` then `calloc` failed somewhy and returned NULL. With fixed printing there is no error in your code here at least https://onlinegdb.com/r1wCaAor8. – Eraklon Mar 15 '20 at 16:51
  • Is this a compiler warning or a runtime error? I can see the compiler warning you about dereferencing a pointer which *might* be NULL (if `calloc` failed), and it would certainly be good practice to check the pointer before proceeding. That said, if your system actually can't allocate 8000 bytes at runtime, you have bigger problems. – Nate Eldredge Mar 15 '20 at 16:55
  • I suppose the printf isn't particularly important, just more to show me that it works! So I'm sure I can rework that to print the array in a proper manner, thank you. It appears its just a compiler warning, so I'll definitely make it check the pointer first. I think the main issue is with the improper use of printf as it now prints a sequence of random symbols. Thank you all – SamuraiMelon Mar 15 '20 at 16:55
  • But as it stands, the printf will at least print garbage, and probably crash. – Nate Eldredge Mar 15 '20 at 16:56
  • As a compilation error, that doesn't make much sense. In theory, `calloc()` could fail at runtime, but the compiler can't diagnose that as an unconditional error. You should check the return value, but the compiler should not complain. – Jonathan Leffler Mar 15 '20 at 16:56
  • It was a compilation warning not an error, obviously big distinctions between the two! Thank you all for your insights. – SamuraiMelon Mar 15 '20 at 17:01

2 Answers2

4

The following message:

Warning C6011   Dereferencing NULL pointer 'x'. Line 14

is not a runtime error. It is a very badly worded warning issued by the Microsoft C++ compiler (see https://learn.microsoft.com/en-us/cpp/code-quality/c6011?view=vs-2019) about the possibility that you might be dereferencing a pointer which might be NULL at runtime.

Your pointer will be NULL if calloc() fails to allocate memory, an eventuality that you probably do not need to worry about, but to keep the compiler happy and prevent the warning, you might want to ASSERT() that the pointer is not NULL before proceeding to dereference the pointer.

And if you want to write perfectly robust code, then you need to add code which makes your function gracefully fail if calloc() returns NULL.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • 1
    “an eventuality that you probably do not need to worry about” — you absolutely *should*. Allocations in C can fail, handle this failure. You can’t do much *about* it, but you should fail with a clear error. – Konrad Rudolph Mar 15 '20 at 17:02
  • @KonradRudolph yes, sure, and I think it may also happen if you have another bug which asks for zero bytes to be allocated. That's why I added the last statement about perfectly robust code. – Mike Nakis Mar 15 '20 at 17:15
1

There is an error in your step calculation. It should be:

double step = (fin - init) / (double)N-1;

For very large arrays, it can be X2 faster if you use the following:

double* linspace(double x1, double x2, int n) {

 double *x = calloc(n, sizeof(double));

 double step = (x2 - x1) / (double)(n - 1);

 for (int i = 0; i < n; i++) {
     x[i] = x1 + ((double)i * step);
 }
 
return x;
}
Darren G
  • 13
  • 2