0

I am studying some routines from Numerical Recipes and I did not understand the use of the macro #define FREE_ARG char* in the implementations to deallocating memory. Here goes one piece of the code:

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define NR_END 1
#define FREE_ARG char*

float *vector(long nl, long nh)
/* allocate a float vector with subscript range v[nl..nh] */
{
    float *v;

    v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
    if (!v) nrerror("allocation failure in vector()");
    return v-nl+NR_END;
}


void free_vector(float *v, long nl, long nh)
/* free a float vector allocated with vector() */
{
    free((FREE_ARG) (v+nl-NR_END));
\\           ^
\\           '----- why?
}

My question is: Why the memory is being released in this manner free((FREE_ARG) (v+nl-NR_END));?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Randerson
  • 775
  • 1
  • 5
  • 19
  • [Please see this discussion on why not to cast the return value of `malloc()` and family in `C`.](http://stackoverflow.com/q/605845/2173917). – Sourav Ghosh Jan 08 '17 at 18:04
  • That whole code looks like a very bad idea. Not only because of the discouraged casts, but also as it allows to `free` a pointer which was not necessarily allocated by `malloc` previously. At least these pointer operations are error-prone. Maybe that is some pre-standard code, but it is possibly illegal for standard C since ca. 28 years. Said that, you should get a more recent book about C code or use that book as ideas, but implement the functions with correct C. – too honest for this site Jan 08 '17 at 18:15

1 Answers1

1

That is probably a very bad code.note

free() takes the argument type void *. Any pointer type can be implicitly converted to a void *, no cast needed.


Note:

In this line

 v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));

the cast is also not required and should be avoided. See this discussion on why not to cast the return value of malloc() and family in C.. This is also one of the reasons behind the usage of bad earlier.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • More crucially, the code exhibits undefined behavior due to bad pointer arithmetic unless `nl == 0`. – EOF Jan 08 '17 at 18:13
  • @EOF Correct in general, however, we don;t know the usage. Notice the return statement also. – Sourav Ghosh Jan 08 '17 at 18:15
  • Looks like some pre-standard rubbish. For modern compilers this code is invitation to disaster. – too honest for this site Jan 08 '17 at 18:18
  • @Olaf Agreed and reflected the same in the very first statement of my answer. :) – Sourav Ghosh Jan 08 '17 at 18:20
  • 1
    From my (little) experience with _Numerical Recipes in C_, that's not only pre-standard, it's literal Fortran code written in C. The addition and subtraction of `NR_END` "adjusts" the 1-based to 0-based inexing. In a quicksort routine I saw, the code uses `l` for the left index, but `ir` for the right index, because implicit typing in Fortan makes everything that begins with `i` to `n` an integer and everything else a real. The book doesn't embrace the language features of C, which makes for bad code. – M Oehm Jan 08 '17 at 18:28
  • 1
    @SouravGhosh: As always you used a much more polite wording. I just wanted to state that more - well - direct :-) – too honest for this site Jan 08 '17 at 18:37
  • @MOehm: I had Pascal in mind which allows arbitrary array-index range, but Fortran would be a reasonable origin, too. And considering the subject, you might be right. – too honest for this site Jan 08 '17 at 18:39
  • @Olaf: Apparently the first edition of [Numerical Recipes](https://en.wikipedia.org/wiki/Numerical_Recipes) had code for both Fortran and Pascal. I didn't know about the Pascal code and had assumed that the original recipes were in Fortran. – M Oehm Jan 08 '17 at 18:50
  • @MOehm: According to the WP article (thanks for the link), it is meant to be C++ adn concentrates on reability ... Even if that above is an older version, especially the latter can only be kidding. – too honest for this site Jan 08 '17 at 21:24