All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Johannes Weiner <hannes@saeurebad.de>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	clameter@sgi.com, penberg@cs.helsinki.fi
Subject: Re: Why is the kfree() argument const?
Date: Wed, 16 Jan 2008 17:33:23 -0500	[thread overview]
Message-ID: <20080116223323.GI30532@goodmis.org> (raw)
In-Reply-To: <alpine.LFD.1.00.0801161026550.2806@woody.linux-foundation.org>

On Wed, Jan 16, 2008 at 10:39:00AM -0800, Linus Torvalds wrote:
> 
> 
> On Wed, 16 Jan 2008, Johannes Weiner wrote:
> > 
> > is there any reason why kfree() takes a const pointer just to degrade it
> > with the call to slab_free()/__cache_free() again?  The promise that the
> > pointee is not modified is just bogus in this case, anyway, isn't it?
> 
> "const" has *never* been about the thing not being modified. Forget all 
> that claptrap. C does not have such a notion.
> 
> "const" is a pointer type issue, and is meant to make certain mis-uses 
> more visible at compile time. It has *no* other meaning, and anybody who 
> thinks it has is just setting himself up for problems.

I totally agree with the above.

> 
> In the particular case of kfree(), the pointer argument *should* be const, 
> and the fact that the C library gets this wrong is not the kernels 
> problem, it's a problem with the C library.

Here, I'm not so sure.

> 
> Why?
> 
>  - From a very obvious and very *real* caller perspective, "free()" really 
>    doesn't change the thing the pointer points to. It does something 
>    totally different: it makes the *pointer* itself invalid.

I'm OK with this.

> 
>    In other words, if you think that "kfree()" changed the thing you 
>    free'd, you're simply wrong. It did no such thing. The memory is 100% 
>    the same, it's just that you cannot access it any more, and if you try, 
>    you'll get somebody elses memory.

This too.

> 
>    In other words, "kfree()" can be const.

Err, not sure.

> 
>  - Anything that *can* take a const pointer should always do so.
> 
>    Why? Because we want the types to be as tight as possible, and normal 
>    code should need as few casts as possible.

OK

> 
>    Here's a question for you: let's say that you have a structure that 
>    has a member that is never changed. To make that obvious, and to allow 
>    the compiler to warn about mis-use of a pointer, the structure should 
>    look something like
> 
> 		struct mystruct {
> 			const char *name;
> 			..
> 
>    and let's look at what happens if the allocation of that const thing is 
>    dynamic.
> 
>    The *correct* way to do that is:
> 
> 		char *name = kmalloc(...)
> 		/* Fill it in */
> 		snprintf(name, ...)
> 		mystruct->name = name;
> 
>    and there are no casts anywhere, and you get exactly the semantics you 
>    want: "name" itself isn't constant (it's obviously modified), but at 
>    the same time the type system makes it very clear that trying to change 
>    it through that mystruct member pointer is wrong.
> 
>    How do you free it?
> 
>    That's right, you do:
> 
> 		kfree(mystruct->name);

This is where I disagree. If a struct has a constant pointer to it, then
the usage of that pointer by the struct should never modify it. If I
need to allocate memory for a name to a struct, I would not expect that
struct to ever free it.

Let's use your example. I'll assume that the struct was created by some
constructor and the destructor freed it. I'd argue the correct way would
be to have the kfree with a typecast.

Why?

  - const pointers (especially strings) should be able to point to
    static data. One thing that we would like to avoid is:

    mystruct->name = "myobj";
	...
    kfree(mystruct->name);

  - really, kfree should match kmalloc for types. What kmalloc returns
    should be what kfree accepts.  Passing in a const pointer to kfree
    *should* be a red flag that something might not be right.

> 
>    and this is why "kfree()" should take a const pointer. If it doesn't, 
>    you have to add an *incorrect* and totally useless cast to code that 
>    was correct.

    char *name = kmalloc(...);
	...
    mystruct->name = name; /* this is an implicit cast */

    So adding a cast to kfree isn't incorrect. C automatically casts
    name to a const pointer, which means if we want to free it, then
    we should cast it back.

> 
> So never believe that "const" is some guarantee that the memory under the 
> pointer doesn't change.  That is *never* true. It has never been true in 
> C, since there can be arbitrary pointer aliases to that memory that aren't 
> actually const. If you think "const *p" means that the memory behind "p" 
> is immutable, you're simply wrong.

Again, I totally agree with the above.

> 
> Anybody who thinks that kfree() cannot (or should not) be const doesn't 
> understand the C type system.

OK, I think that kfree should not be const, but not because of the
explanation that you gave, but because of the C type system in general.

kfree should match the kmalloc type. We don't declare

  const void *kmalloc(...)

so we shouldn't do the same with kfree. If you assign a const pointer to
something from kmalloc, C implicitly does the cast. This doesn't mean
that we should ignore doing the cast back in kfree. Especially since
this could help us avoid the kfree("mystring") issue.

Just my $0.02

-- Steve


  parent reply	other threads:[~2008-01-16 22:35 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-16 16:32 Why is the kfree() argument const? Johannes Weiner
2008-01-16 16:48 ` Christoph Lameter
2008-01-16 17:34   ` Bernd Petrovitsch
2008-01-16 17:45   ` Pekka J Enberg
2008-01-16 18:39 ` Linus Torvalds
2008-01-16 22:19   ` Johannes Weiner
2008-01-16 22:20     ` Christoph Lameter
2008-01-16 22:37       ` Johannes Weiner
2008-01-16 23:13       ` Johannes Weiner
2008-01-16 23:18       ` Linus Torvalds
2008-01-16 23:16     ` Linus Torvalds
2008-01-16 22:33   ` Steven Rostedt [this message]
     [not found] <MDEHLPKNGKAHNMBLJOLKIEGIJJAC.davids@webmaster.com>
2008-01-17 21:25 ` Linus Torvalds
2008-01-17 22:28   ` David Schwartz
2008-01-17 23:10     ` Linus Torvalds
2008-01-18  0:56       ` David Schwartz
2008-01-18  1:15         ` Linus Torvalds
2008-01-18  5:02           ` David Schwartz
2008-01-18 15:38             ` Chris Friesen
2008-01-18 16:10             ` Linus Torvalds
2008-01-18 20:55               ` David Schwartz
2008-01-18 17:37             ` Olivier Galibert
2008-01-18 18:06             ` DM
2008-01-18  7:51           ` Giacomo Catenazzi
2008-01-18  8:20             ` Giacomo Catenazzi
2008-01-18 13:53               ` Andy Lutomirski
2008-01-18 17:24                 ` Olivier Galibert
2008-01-18 22:29                   ` J.A. Magallón
2008-01-18 23:44                     ` Krzysztof Halasa
2008-01-18 13:54               ` Andy Lutomirski
2008-01-18 19:14                 ` Vadim Lobanov
2008-01-18 19:31                   ` Zan Lynx
2008-01-18 19:55                     ` Vadim Lobanov
2008-01-18  8:30             ` Vadim Lobanov
2008-01-18  9:48   ` Jakob Oestergaard
2008-01-18 11:47     ` Giacomo A. Catenazzi
2008-01-18 14:39       ` Jakob Oestergaard
2008-01-18 19:06       ` Vadim Lobanov
2008-01-18 13:31     ` Björn Steinbrink
2008-01-18 14:53       ` Jakob Oestergaard
  -- strict thread matches above, loose matches on Subject: below --
2008-01-18 12:45 ecolbus
2008-01-18 15:20 ` Giacomo A. Catenazzi
2008-01-18 16:45 ecolbus
2008-01-18 18:20 ` Olivier Galibert
2008-01-18 19:10 ecolbus
     [not found] <fa.cHMztHfqJXv7vw5O0nQ8SdTrma0@ifi.uio.no>
     [not found] ` <fa.V9M+5l8C/um5KEiBtZOjbJDQmu4@ifi.uio.no>
2013-01-12 19:18   ` antoine.trux
2013-01-13  8:10     ` Chen Gang F T
2013-01-13 17:41       ` Guenter Roeck
2013-01-14  1:45         ` Chen Gang F T
2013-01-13 20:54       ` Cong Ding
2013-01-14  1:18         ` Chen Gang F T

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080116223323.GI30532@goodmis.org \
    --to=rostedt@goodmis.org \
    --cc=clameter@sgi.com \
    --cc=hannes@saeurebad.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=penberg@cs.helsinki.fi \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.