Question about memory allocation??

Discussion in 'C Programming' started by sethukr@gmail.com, Dec 14, 2006.

  1. Guest

    Hi everybody,

    While running the following program in GCC, i'm very much screwed.

    main()
    {
    char *ptr1;
    char arr[1];
    int i;
    char *ptr2;

    ptr1 = (char *)malloc(1);
    ptr2 = (char *)malloc(1);


    printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
    like, 000053

    printf("\n address of arr : %u\n", arr); /* shows 000052

    printf("\n address of i : %u\n", &i); /* shows 000045

    printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041
    }

    **Why the memory is allocated from bottom to top?? ( in the order
    ptr2, i , arr, and ptr1)

    **Integer takes only 4-bytes, it occupies 000045 to 000048.

    **What happened to the memory between 000049 to 000051 here??

    Can anybody tell me why this magic is happened??

    Thanks in advance,
    Sethu
     
    , Dec 14, 2006
    #1
    1. Advertising

  2. wrote:
    > Hi everybody,
    >
    > While running the following program in GCC, i'm very much screwed.


    That's not possible. You compile your program with GCC, you run it in
    whatever operating system you are using.

    > main()


    Old-style definition. Better to be explicit: int main(void)

    > {
    > char *ptr1;
    > char arr[1];
    > int i;
    > char *ptr2;
    >
    > ptr1 = (char *)malloc(1);
    > ptr2 = (char *)malloc(1);


    Don't cast malloc's result unless you know what you're doing. You
    don't. The proper way to get rid of the warning that you get without it
    is to include <stdlib.h>.

    > printf("\n & ptr1 : %u\n", &ptr1);


    If you use printf, you need a proper prototype. Include <stdio.h>.
    After fixing that, %u is the format specifier for unsigned int. It is
    not the format specifier for any type of pointer. The way to print
    pointers is to convert them to void *, and then use printf's %p format
    specifier.

    > /* I got outputs
    > like, 000053


    /* comments require a matching */.

    > printf("\n address of arr : %u\n", arr); /* shows 000052
    >
    > printf("\n address of i : %u\n", &i); /* shows 000045
    >
    > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041
    > }
    >
    > **Why the memory is allocated from bottom to top?? ( in the order
    > ptr2, i , arr, and ptr1)


    Because that is the way your operating system works. As for why your
    operating system works that way, it could be because that happens to be
    the most efficient method for your processor type, it could be for
    compatibility with other systems, it could be because it was easier to
    implement, or it could be for any number of other reasons.

    > **Integer takes only 4-bytes, it occupies 000045 to 000048.


    It's possible but extremely unlikely that the addresses used are
    actually 45 through 48. What's more likely is that you get misleading
    output because you lied to the compiler. Do you get different addresses
    with %p?

    > **What happened to the memory between 000049 to 000051 here??


    It's not used.

    > Can anybody tell me why this magic is happened??


    It's hardly magic. It's because your compiler decided it would be a
    better idea to waste three bytes of memory than to deal with the
    problems caused by using it. These problems vary from processor to
    processor, and even from operating system to operating system, but
    generally speaking, programs can crash or run much more slowly if the
    compiler does not make sure variables of certain types are not stored
    at specific addresses. Which types and which addresses are again
    specific to your processor and operating system.
     
    =?utf-8?B?SGFyYWxkIHZhbiBExLNr?=, Dec 14, 2006
    #2
    1. Advertising

  3. said:

    > Hi everybody,
    >
    > While running the following program in GCC, i'm very much screwed.
    >
    > main()
    > {
    > char *ptr1;
    > char arr[1];
    > int i;
    > char *ptr2;
    >
    > ptr1 = (char *)malloc(1);


    Undefined behaviour: you forgot the prototype for malloc. See recent
    comp.lang.c discussion in the thread entitled "malloc".

    > ptr2 = (char *)malloc(1);
    >
    >
    > printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
    > like, 000053


    Undefined behaviour: (a) you forgot the prototype for printf, and (b) you
    gave a pointer value to printf when it was expecting an unsigned int. Each
    of these is sufficient cause for the program to behave in any way
    whatsoever.

    > **Why the memory is allocated from bottom to top?? ( in the order
    > ptr2, i , arr, and ptr1)


    Why shouldn't it be?

    > **Integer takes only 4-bytes, it occupies 000045 to 000048.
    >
    > **What happened to the memory between 000049 to 000051 here??


    Compilers will often align pointers on boundaries that are multiples of a
    given (typically small) integer.

    > Can anybody tell me why this magic is happened??


    When you break the rules of C, anything can happen.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, Dec 14, 2006
    #3
  4. Chris Dollin Guest

    wrote:

    > Hi everybody,
    >
    > While running the following program in GCC, i'm very much screwed.


    I don't see why. ("Screwed" in this context usually means "it broke,
    and this was a Very Bad Thing".)

    > main()


    `int main(void)` is preferred; and the `int` is /necessary/ for C99.

    > {
    > char *ptr1;
    > char arr[1];
    > int i;
    > char *ptr2;
    >
    > ptr1 = (char *)malloc(1);


    You should #include <stdlib.h> if you're mallocating. And the `(char*)` is
    unnecessary (and unwise). I'd also use `malloc(sizeof(*ptr1))` because that's
    part of a general safe pattern.

    > ptr2 = (char *)malloc(1);
    >
    >
    > printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
    > like, 000053


    You should #include <stdio.h> if you're printfing.

    You were unlucky. `&ptr1` is a pointer value, not an integer: you
    should use the `%p` format and cast to `(void*)` to ensure safe
    portability.

    Otherwise you get Undefined Behaviour: all bets about your code's
    behaviour are off.

    > printf("\n address of arr : %u\n", arr); /* shows 000052
    >
    > printf("\n address of i : %u\n", &i); /* shows 000045
    >
    > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041


    Dittoes.

    > }
    >
    > **Why the memory is allocated from bottom to top?? ( in the order
    > ptr2, i , arr, and ptr1)


    Why not? The order of placement is the compiler's business. It can
    allocate in whatever order it finds convenient. Maybe it's allocating
    on a "stack" which "grows downwards". Who cares? [1]

    > **Integer takes only 4-bytes, it occupies 000045 to 000048.
    >
    > **What happened to the memory between 000049 to 000051 here??


    I expect it's been eaten by alignment issues.

    > Can anybody tell me why this magic is happened??


    This is C. There is /no magic/ (except as permitted by Undefined
    Behavior).

    The compiler will allocate local variables as convenient and
    efficient as directed. Usually you don't need to care.

    [1] /Some/ people care. Usually they're obliged to use some specific
    implementation and know exactly why they care.

    --
    Chris "Perikles triumphant" Dollin
    "We did not have time to find out everything we wanted to know."
    - James Blish, /A Clash of Cymbals/
     
    Chris Dollin, Dec 14, 2006
    #4
  5. <> wrote:
    > While running the following program in GCC, i'm very much screwed.


    Missing headers:

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

    > main()


    Make that

    int main( void )

    > {
    > char *ptr1;
    > char arr[1];
    > int i;
    > char *ptr2;


    > ptr1 = (char *)malloc(1);


    Don't cast the return value of malloc() - it won't buy you anything
    but will keep the compiler from complaining if you forgot to include
    <stdlib.h>, which can result in ugly bugs on some platforms.

    > ptr2 = (char *)malloc(1);


    > printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
    > like, 000053


    The correct way to print pointers is to use "%p", used with the
    pointer cast to a void pointer, e.g.

    printf("\n & ptr1 : %p\n", ( void * ) &ptr1);

    > printf("\n address of arr : %u\n", arr); /* shows 000052


    > printf("\n address of i : %u\n", &i); /* shows 000045


    > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041


    You forgot to return an int here as it is expected of main().

    > }


    > **Why the memory is allocated from bottom to top?? ( in the order
    > ptr2, i , arr, and ptr1)


    That memory isn't "allocated", at least not in the sense of
    functions like malloc() etc. The compiler must make sure that
    memory is available for local variables when the function is
    called. How it does that is completely up to the implementation.
    And the addresses of these variables can be wherever the compiler
    likes them to be - it could even have different areas of memory
    for ints, chars, pointers etc. (it also might "optimize out"
    some of the local variables and just keep them in CPU registers).
    If you plan to use some tricks because you believe you know how
    your compiler is doing it, that's up to you, but you won't writ
    C programs anymore that are portable - you're rather likely to
    invoke undefined behaviour.

    > **Integer takes only 4-bytes, it occupies 000045 to 000048.
    > **What happened to the memory between 000049 to 000051 here??


    That's strictly for the compiler to decide which also has to take
    into account alignment issues.

    > Can anybody tell me why this magic is happened??


    The only way to find out about your compiler and the architecture
    you're on (but mind, a different compiler will may do it differently,
    and even the same compiler may do it differently when the program
    gets compiled for a different arcitecture!) is to either read the
    code for the compiler or ask its writers.

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Dec 14, 2006
    #5
  6. On Thu, 14 Dec 2006, wrote:

    > Hi everybody,
    >
    > While running the following program in GCC, i'm very much screwed.


    >


    You must #include <stdlib.h> if you want to use malloc()

    > main()
    > {
    > char *ptr1;
    > char arr[1];
    > int i;
    > char *ptr2;
    >
    > ptr1 = (char *)malloc(1);
    > ptr2 = (char *)malloc(1);
    >
    >


    The correct printf() format specifier for printing pointers is %p, not %u!

    > printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
    > like, 000053
    >
    > printf("\n address of arr : %u\n", arr); /* shows 000052
    >
    > printf("\n address of i : %u\n", &i); /* shows 000045
    >
    > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041
    > }
    >
    > **Why the memory is allocated from bottom to top?? ( in the order
    > ptr2, i , arr, and ptr1)
    >


    Because the C standard does not disallow this. Most likely it's easier for
    the compiler to allocate variables this way if the machine uses a stack
    that grows towards lower addresses. Try to understand that you cannot rely
    on this in your programs. Even for gcc, passing different optimization
    flags (e.g. -O3 (optimize for speed) vs -Os (optimize for space)) will
    give different results.



    > **Integer takes only 4-bytes, it occupies 000045 to 000048.
    >
    > **What happened to the memory between 000049 to 000051 here??
    >


    Perhaps the compiler decided that pointers have to be aligned at an
    address which is a multiple of 4. Nowhere in the standard says that
    variables have to be allocated one after the other, or even in the order
    in which they are defined, and aligning variables in general results
    better runtime performance.


    > Can anybody tell me why this magic is happened??



    The definite answer can be found by studying the gcc internals manual or
    even better the gcc source.

    >
    > Thanks in advance,
    > Sethu
    >
    >

    Emil
     
    Kohn Emil Dan, Dec 14, 2006
    #6
  7. Chris Dollin wrote:
    >
    > wrote:

    [...]
    > > Can anybody tell me why this magic is happened??

    >
    > This is C. There is /no magic/ (except as permitted by Undefined
    > Behavior).

    [...]

    Well, one could say that there is "magic", at least as far as the
    application is concerned.

    Q: How does free() know how much memory was allocated?
    A: Magic.

    --
    +-------------------------+--------------------+-----------------------+
    | Kenneth J. Brody | www.hvcomputer.com | #include |
    | kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------+
    Don't e-mail me at: <mailto:>
     
    Kenneth Brody, Dec 14, 2006
    #7
  8. goose Guest

    Jens Thoms Toerring wrote:
    > <> wrote:
    >

    <snipped>
    >
    > > printf("\n address of arr : %u\n", arr); /* shows 000052

    >
    > > printf("\n address of i : %u\n", &i); /* shows 000045

    >
    > > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041

    >

    <snipped>
    >
    > And the addresses of these variables can be wherever the compiler
    > likes them to be - it could even have different areas of memory
    > for ints, chars, pointers etc. (it also might "optimize out"
    > some of the local variables and just keep them in CPU registers).


    I'd be interested to know how an implementation plans to return
    the address of a register.

    goose,
     
    goose, Dec 14, 2006
    #8
  9. goose <> wrote:

    > Jens Thoms Toerring wrote:
    > > <> wrote:
    > >

    > <snipped>
    > >
    > > > printf("\n address of arr : %u\n", arr); /* shows 000052

    > >
    > > > printf("\n address of i : %u\n", &i); /* shows 000045

    > >
    > > > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041

    > >

    > <snipped>
    > >
    > > And the addresses of these variables can be wherever the compiler
    > > likes them to be - it could even have different areas of memory
    > > for ints, chars, pointers etc. (it also might "optimize out"
    > > some of the local variables and just keep them in CPU registers).


    > I'd be interested to know how an implementation plans to return
    > the address of a register.


    If you take the address of a variable the compiler knows that it
    can't "optimize out" the variable - but you usually don't print
    out addresses, this was only done by the OP in order to find out
    where the compiler puts the local variables.

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Dec 14, 2006
    #9
  10. "" <> writes:
    > While running the following program in GCC, i'm very much screwed.
    >
    > main()
    > {
    > char *ptr1;
    > char arr[1];
    > int i;
    > char *ptr2;
    >
    > ptr1 = (char *)malloc(1);
    > ptr2 = (char *)malloc(1);
    >
    >
    > printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
    > like, 000053
    >
    > printf("\n address of arr : %u\n", arr); /* shows 000052
    >
    > printf("\n address of i : %u\n", &i); /* shows 000045
    >
    > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041
    > }


    Here's a corrected version of your program:

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

    int main(void)
    {
    char *ptr1;
    char arr[1];
    int i;
    char *ptr2;

    ptr1 = malloc(1);
    ptr2 = malloc(1);

    printf("&ptr1 = %p\n", (void*)&ptr1);
    printf("arr = %p\n", (void*)arr);
    printf("&i = %p\n", (void*)&i);
    printf("&ptr2 = %p\n", (void*)&ptr2);

    return 0;
    }

    What I've done:

    You're calling printf(), so the "#include <stdio.h>" is mandatory.
    You're calling malloc(), so the "#include <stdlib.h>" is mandatory.

    (Well, not *quite*; there are other ways to acheive the same
    effect, but there's absolutely no point in using them. The
    "#include" is the right way to do this.

    Don't cast the result of malloc(). Doing so can mask certain errors,
    such as omitting the required "#include <stdlib.h>" or incorrectly
    using a C++ compiler to compile C code.

    A good pattern for using malloc() is:

    ptr = malloc(sizeof *ptr);

    or, if you want to allocate an array:

    ptr = malloc(COUNT * sizeof *ptr);

    I've used the simpler "malloc(1)" here since you're only allocating a
    single character (and sizeof(char) is 1 by definition). But if you're
    going to be changing the code in the future, the lines:

    ptr1 = malloc(1);
    ptr2 = malloc(1);

    should probably be written as:

    ptr1 = malloc(sizeof *ptr1);
    ptr2 = malloc(sizeof *ptr2);

    The way to print a pointer value with printf is to convert it to void*
    (one of the few cases where a cast is correct and necessary) and use
    the "%p" format. The result of the "%p" format is
    implementation-specific; it can be a number in hexadecimal, decimal,
    octal, or even something other than a number. On the implementations
    I use, it's a hexadecimal number corresponding to the representation
    of the address. But remember that addresses *are not* numbers;
    they're addresses.

    I don't know why you called malloc(). You allocate one byte each for
    ptr1 and ptr2 to point to, but you never use that allocated memory.
    (You're printing the addresses of the pointer objects themselves,
    *not* the addresses of what they point to.) If you are going to use
    the allocated memory, you should *always* check the result of
    malloc(); it returns a null pointer value on failure. (There's not
    always a good way to handle this failure, but even aborting the
    program with an error message is likely to be better than blindly
    ignoring the problem.)

    > **Why the memory is allocated from bottom to top?? ( in the order
    > ptr2, i , arr, and ptr1)


    Why not? Who cares?

    It's the compiler's job to worry about where and how variables should
    be allocated. It does this so you don't have to. It will allocate
    local variables in whatever way the compiler's author decided made the
    most sense. There may or may not be a consistent order. There may or
    may not be gaps to allow for alignment. There *will* be a unique and
    valid address for each declared variable, and that's really all you
    need to know. If you write code that depends on the details of how
    things are allocated, that code is non-portable, and it will break
    when you try it with another compiler.

    You're likely to find the comp.lang.c FAQ illuminating; it's an
    excellent resource, thanks to a lot hard work by Steve Summit. It's
    at <http://www.c-faq.com/>. Don't expect to be able to read the whole
    thing in one sitting. If you like, you can start by reading bits and
    pieces of it -- and you should always check it before posting a
    question here.

    But the FAQ is a set of answers to specific questions, not a tutorial.
    You should also have a good book or other C tutorial. K&R2 (Kernighan
    & Ritchie, _The C Programming Language_, 2nd edition) is generally
    acknowledged to be the best tutorial, but it helps to have some
    programming experience. For other resources, see the FAQ.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Dec 14, 2006
    #10
  11. malc Guest

    Keith Thompson <> writes:

    > "" <> writes:
    >> While running the following program in GCC, i'm very much screwed.


    [..snip..]

    > Don't cast the result of malloc(). Doing so can mask certain errors,
    > such as omitting the required "#include <stdlib.h>" or incorrectly
    > using a C++ compiler to compile C code.
    >
    > A good pattern for using malloc() is:
    >
    > ptr = malloc(sizeof *ptr);
    >
    > or, if you want to allocate an array:
    >
    > ptr = malloc(COUNT * sizeof *ptr);


    Opinions on whether this is a good pattern vary:
    http://lkml.org/lkml/2005/9/18/29

    Perhaps you can add something in support of the 'good pattern' argument
    not expressed in the aforementioned thread?

    [..snip..]

    --
    vale
     
    malc, Dec 14, 2006
    #11
  12. "goose" <> writes:
    > Jens Thoms Toerring wrote:
    >> <> wrote:
    >>

    > <snipped>
    >>
    >> > printf("\n address of arr : %u\n", arr); /* shows 000052

    >>
    >> > printf("\n address of i : %u\n", &i); /* shows 000045

    >>
    >> > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041

    >>

    > <snipped>
    >>
    >> And the addresses of these variables can be wherever the compiler
    >> likes them to be - it could even have different areas of memory
    >> for ints, chars, pointers etc. (it also might "optimize out"
    >> some of the local variables and just keep them in CPU registers).

    >
    > I'd be interested to know how an implementation plans to return
    > the address of a register.


    On some hardware, registers have addresses. (This isn't the case on
    most modern systems.)

    More commonly, a compiler might allocate a memory location for a
    variable, but keep its value in a register for part of its lifetime,
    storing it from the register to memory only when its address is
    needed. This isn't quite "optimizing it out", but it's close. (And
    no, this doesn't really involve returning the address of a register,
    so it's not *quite* responsive to your question.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Dec 14, 2006
    #12
  13. malc <> writes:
    > Keith Thompson <> writes:
    >> "" <> writes:
    >>> While running the following program in GCC, i'm very much screwed.

    >
    > [..snip..]
    >
    >> Don't cast the result of malloc(). Doing so can mask certain errors,
    >> such as omitting the required "#include <stdlib.h>" or incorrectly
    >> using a C++ compiler to compile C code.
    >>
    >> A good pattern for using malloc() is:
    >>
    >> ptr = malloc(sizeof *ptr);
    >>
    >> or, if you want to allocate an array:
    >>
    >> ptr = malloc(COUNT * sizeof *ptr);

    >
    > Opinions on whether this is a good pattern vary:
    > http://lkml.org/lkml/2005/9/18/29
    >
    > Perhaps you can add something in support of the 'good pattern' argument
    > not expressed in the aforementioned thread?
    >
    > [..snip..]


    The cited web page does raise some interesting arguments. It talks
    about kmalloc rather than malloc, but the point is the same. To
    summarize, the author (one Russell King) argues that
    p = malloc(sizeof(struct foo));
    is superior to
    p = malloc(sizeof *p);

    Why? Because for certain code changes, you're going to want to search
    the code base for references to type "struct foo"; using the "sizeof *p"
    form effectively hides the allocation from such a search.

    (But please don't depend on my summary; since I don't necessarily
    agree with the argument, I'm likely to present it incorrectly.)

    In my opinion, the "sizeof *p" form is still to be preferred. To
    someone reading the code, it's obviouly correct *without* searching to
    find the declaration of p. The line:
    p = malloc(sizeof(struct foo));
    will be happily accepted by the compiler, but it's incorrect if p
    happens to be of type struct bar* rathar than struct foo*. In either
    case, you have to maintain consistency between the pointer
    (particularly what it points to) and the argument passed to malloc().
    The "sizeof *p" form makes it easy to do this, because it only has to
    be consistent within a single line. To verify that the "sizeof(struct
    foo)" form is correct, you have to track down the declaration of p.
    Some tools may do this for you. Are any compilers capable of
    recognizing the "sizeof(struct foo)" idiom and issuing a warning if
    the target is of a different type?

    As far as the maintenance argument goes, a search for "struct foo"
    should take you to the declaration of "p" (which will have a much
    better, name, *right?*). From there, you still need to track down
    uses of p to make sure you've accounted for any changes. It's not
    clear to me that using the type name in the malloc() call is all that
    helpful. But then again, it's not entirely clear to me that it isn't.

    Again, though, the cited web page does raise some interesting
    arguments, and I wouldn't mind seeing some feedback from the other
    regulars here.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Dec 15, 2006
    #13
  14. goose Guest

    malc wrote:
    > Keith Thompson <> writes:


    <snipped>

    > > A good pattern for using malloc() is:
    > >
    > > ptr = malloc(sizeof *ptr);
    > >
    > > or, if you want to allocate an array:
    > >
    > > ptr = malloc(COUNT * sizeof *ptr);

    >
    > Opinions on whether this is a good pattern vary:
    > http://lkml.org/lkml/2005/9/18/29
    >
    > Perhaps you can add something in support of the 'good pattern' argument
    > not expressed in the aforementioned thread?
    >


    I'll address the authors points in the same order he presents
    them:
    1. He says -
    "1. The above implies that the common case is that we are changing
    the names of structures more frequently than we change the contents
    of structures. Reality is that we change the contents of
    structures
    more often than the names of those structures.


    Why is this relevant? If you change the contents of structures,
    they need checking for initialisation. How do you find all the
    locations that need initialisation checked? Via grep. The problem
    is that:

    p = kmalloc(sizeof(*p), ...)

    is not grep-friendly, and can not be used to identify potential
    initialisation sites. However:

    p = kmalloc(sizeof(struct foo), ...)

    is grep-friendly, and will lead you to inspect each place where
    such a structure is allocated for correct initialisation."

    I say -
    This is certainly a valid argument but rather than using
    grep to find all the malloc calls, I'd rather find all
    declarations for "struct foo *p;" and double-check initialisation
    (which will not occur far from the point) of p and, while I'm
    at it, check that all serialisation of the struct is correct.

    The reason is that, assuming we religiously follow the authors
    convention, there will still be quite a few structs (and pointers
    to structs) which are initialised *without* malloc. So we
    will still have to hunt down all objects of type "struct foo" and
    "struct foo *" anyway.
    -------------------------------------
    2. He says -
    "2. in the rare case that you're changing the name of a structure,
    you're
    grepping the source for all instances for struct old_name, or doing
    a search and replace for struct old_name. You will find all
    instances
    of struct old_name by this method and the bug alluded to will not
    happen."

    I say -
    Correct; but you will have less to change by doing
    grep -d recurse old_name | grep -v malloc
    There is no need to make malloc dependent on artificial
    restraints in order to function correctly, so why do so?

    -------------------------------------
    3. He says -
    "3. if you are changing the name of a structure, in order to ensure
    that
    everyone gets fixed up correctly, you do not want to keep an old
    declaration of the structure around, unless you have a very very
    good
    reason to do so. This will ensure that any missed old structure
    names (eg, because of merging of independent concurrent threads of
    development) get caught. As a result, any sizeof(struct) also gets
    caught."

    I say -
    Here the author is just grasping at straws; he makes the argument
    that "sizeof (struct old_name)" is better because all references
    to old_name must be fixed when changing structure to "struct
    new_name".
    By avoiding even using old_name, there is nothing to "catch".

    There is, in all of that above, only one halfway good justification,
    but
    the author *does* go on to say that the assertion that "malloc (sizeof
    *p)"
    method is better is flawed.

    goose,


    -------------------------------------
     
    goose, Dec 15, 2006
    #14
  15. MJ_India Guest

    wrote:

    > **Why the memory is allocated from bottom to top?? ( in the order
    > ptr2, i , arr, and ptr1)
    >


    Though behavior may differ with change of system and compiler, but when
    I checked this with my pentium machine and tcc (int is 16 bit)
    compiler, observation was as follows:

    variables ptr1, arr, i and ptr2 were lodged at addresses BP - 2, BP -
    4, BP - 6 and BP - 8 respectively. And thus the result. (BP is Base
    pointer, usually all local variables are refereced with some offset of
    this base pointer i.e. "BP - some offset" on X86 architecture. and thus
    all local variable can be seen as a stack in memory starting from
    address stored in BP. BP itself points to the return address of current
    routine. (due to end of routine or return statement))

    But Sethu the result was different on my redhat linux pentium machine.

    About integer variable (int i) address, behavior differs with
    endian-ness of machine as well.

    Hope you got what I say -MJ
     
    MJ_India, Dec 15, 2006
    #15
  16. Randy Howard Guest

    Keith Thompson wrote
    (in article <>):

    > The cited web page does raise some interesting arguments. It talks
    > about kmalloc rather than malloc, but the point is the same. To
    > summarize, the author (one Russell King) argues that
    > p = malloc(sizeof(struct foo));
    > is superior to
    > p = malloc(sizeof *p);
    >
    > Why? Because for certain code changes, you're going to want to search
    > the code base for references to type "struct foo"; using the "sizeof *p"
    > form effectively hides the allocation from such a search.
    >
    > (But please don't depend on my summary; since I don't necessarily
    > agree with the argument, I'm likely to present it incorrectly.)


    They're more interested in grep than code correctness, or at
    least that particular guy was. The fact is, if you want code
    that needs to be found on wholesale changes to a structure to be
    found, mark it with a comment like:

    /* GREPME: I must be updated here if struct foo changes */

    and stop being a lazy knob...

    ymmv.


    --
    Randy Howard (2reply remove FOOBAR)
    "The power of accurate observation is called cynicism by those
    who have not got it." - George Bernard Shaw
     
    Randy Howard, Dec 16, 2006
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. s.subbarayan

    Dynamic memory allocation and memory leak...

    s.subbarayan, Mar 18, 2005, in forum: C Programming
    Replies:
    10
    Views:
    720
    Eric Sosman
    Mar 22, 2005
  2. Rodrigo Dominguez

    memory allocation and freeing memory

    Rodrigo Dominguez, Jun 13, 2005, in forum: C Programming
    Replies:
    11
    Views:
    615
    Jean-Claude Arbaut
    Jun 15, 2005
  3. Ken
    Replies:
    24
    Views:
    3,896
    Ben Bacarisse
    Nov 30, 2006
  4. chris
    Replies:
    6
    Views:
    1,007
    chris
    Oct 28, 2005
  5. Bjarke Hammersholt Roune
    Replies:
    14
    Views:
    1,207
    Bjarke Hammersholt Roune
    Mar 6, 2011
Loading...

Share This Page