1

While reading this article, I came across this paragraph:

Pointers to objects may have the same size but different formats. This is illustrated by the code below:

int *p = (int *) malloc(...); ... free(p);

This code may malfunction in architectures where int * and char * have different representations because free expects a pointer of the latter type.

And this is not the first time I read that free expects a char* type.

My question is, how to free p?

Patrick Trentin
  • 7,126
  • 3
  • 23
  • 40
Bite Bytes
  • 1,455
  • 8
  • 24
  • 2
    `free` takes a `void *`, not a `char *`. Get a recent (i.e. not older than 18 years and about modern C) book. That will also explain the semantics and not to cast the result of `malloc` & friends. – too honest for this site Sep 07 '17 at 16:06
  • 3
    But [`free`](http://en.cppreference.com/w/c/memory/free) expects a `void *` as argument. The article you link to is *very* old. Also, the likelihood of you ever finding a system where different pointer-types have different representations are slim to none (unless you want to specialize in ancient systems and computer archeology) – Some programmer dude Sep 07 '17 at 16:06
  • @Someprogrammerdude even that the article is old, the writers are aware of the Standard C. So I guess the paragraph is wrong rather than old. – Bite Bytes Sep 07 '17 at 16:09
  • 1
    @BiteBytes But C wasn't really standardized until 1989 (ANSI) and 1990 (ISO), so by the the time the article was originally written there might have been plenty of pre-standard compilers available. Today the only widely available C compiler that's not up to modern standards is the Microsoft Visual Studio C compiler (it's still fully C89/90 compliant though). – Some programmer dude Sep 07 '17 at 16:14
  • @Someprogrammerdude The article was written in `Nov 1990, 8th Revision` and as I mentioned, the authors are aware of the Standard, and they have a whole section talking about ANSI C. – Bite Bytes Sep 07 '17 at 16:16
  • 1
    Well it *is* about portability, and at the time not all compilers were standards-compliant, which is probably the reason for the quotes you have. So to be portable (at that time) one could not assume that the `free` function took a `void *` argument (or that `malloc` returned a `void *`). – Some programmer dude Sep 07 '17 at 16:20
  • @Someprogrammerdude Sure, but the document also states that "we must restrict ourselves to programs which must execute under Unix-like operating systems and those which implement a reasonable Unix-like environment"... No modern-day Unix-like OS uses such prehistoric C compilers or standard libraries. I linked to the POSIX standard in my answer, which is the de-facto requirement for Unix-like OSes; in fact, if an OS is to be declared "Unix" it must adhere strictly to that manual. – autistic Sep 07 '17 at 16:26
  • I've favourited this question to ensure there's a chance for it to exist un-closed, as this is a very real problem that can be observed in the realm of C programming. Many students rely upon out-of-date resources, particularly those from developing nations such as India, and we need questions like these to hint to them that they should upgrade! @BiteBytes, you're not the only one, so it's great to see you're not taking this personally. Please let me know if this question gets closed and I don't notice. – autistic Sep 07 '17 at 16:35
  • @Seb That kind of my point. The document is old, and so is its information. Which you also point out in your answer. – Some programmer dude Sep 07 '17 at 16:46

1 Answers1

4

NOTE: You should not cast the return value of malloc in C.

This question illustrates the dangers of reading potentially invalid resources. It's extremely important to ensure the resource you read is accurate! OPs resource in question, is not wrong for its era, but is well out-of-date and, consequently, is invalid. K&R 2E is ironically one year older, but is still very much in date (and thus still highly recommended) because it follows the standard.

If we consult a more reputable resource (the free manual), we can see that free actually expects the pointer to be of void * type:

void free(void *ptr);

... and for what it's worth, here's the malloc manual showing that malloc returns void *:

void *malloc(size_t size);

In both cases, as described by C11/6.3.2.3p1 (the C11 standard):

A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.

int *p = malloc(...); // A conversion occurs here; `void *` as returned by malloc is converted to `int *`
free(p);              // ... and the reverse of the conversion occurs here, to complete the cycle mentioned in C11/6.3.2.3p1

NOTE (in case you missed it the first time): You should not cast the return value of malloc in C. After all, you don't need to cast it when you pass it to free, right?

autistic
  • 1
  • 3
  • 35
  • 80
  • I already studied K&R, and I'm aware of the fact that `free` takes a `void*`, I just wanted to make sure that the document is inaccurate by asking on SO. – Bite Bytes Sep 07 '17 at 16:42
  • From the article I quote: **"Besides the type void * which is mentioned in the next section, the Standard has introduced the type long double."**. As you can see, they are aware of **void*** and the **Standard**. So it's not a matter of being old. – Bite Bytes Sep 07 '17 at 16:51
  • 1
    Well, now you know... and like some of my questions which are of a similar "I need validation" nature, I reckon this question will be (incorrectly) closed, and then later deleted. Let me know when it is, because this question should stay. Yes, the article mentions the standard and K&R2E, yet still maintains that portability prior to those resources is necessary... Back in those days was the case, but not now, especially for "Unix-like OSes" (which POSIX/the Open Group defines). – autistic Sep 07 '17 at 16:56
  • 1
    I want to point out that the resource is not *wrong*; in fact, from a historical point of view, considering the *historical definition of C* prior to C89, and even during the transitional period between C89 and C99 for any systems which still used the old pre-C89 compilers, this document has some *truth*. You'd be hard-pressed finding such compilers nowadays, so this is a non-concern... and for any C89, C99 or C11 implementation *this is wrong*. It's *invalid* because it's possibly wrong, not because it's always wrong (because after all, sometimes it's right). – autistic Sep 07 '17 at 17:00