Re: Weird malloc behaviour



Thank you for the suggestions, I will apply them in the "real
code" (this was just a test routine btw written in haste, although I
must admit that I still get quite brain damaged by type casting ;))...

Regards
Nicola

On 31 Lug, 09:58, santosh <santosh....@xxxxxxxxx> wrote:
lept...@xxxxxxxxx wrote:
Ok, I followed your suggestions and edited the code like this:

///////////////////////////////////////////////////////////////

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

typedef struct {
int a;
int b;
int c;
} BEAM_PROFILE;

void main(void){

This is not portable. Use int main(void) instead.

    BEAM_PROFILE * bpp;
    unsigned long lpp;

    printf("sizeof(*BEAM_PROFILE) is %d\n", sizeof(BEAM_PROFILE*));

Or

  printf("sizeof(BEAM_PROFILE*) is %lu\n", (unsigned long)sizeof bpp);

    printf("sizeof(lpp) is %d\n", sizeof(lpp));

Be aware that the result of an application of the sizeof operator is a
value of type size_t, which is an implementation defined unsigned
integer type. Under C90 it must be a typedef for one of unsigned char,
unsigned short, unsigned int, or unsigned long, the only unsigned
integer types defined. However it's not easily possible at runtime to
know which of these types is actually typedef'ed to size_t. That is why
it is safer to print the value as an unsigned long and cast the
corresponding argument appropriately.

Under C99 a new printf/scanf specifier 'z' has been added specifically
for size_t arguments, but unfortunately, C99 itself is not very
portable.

In any case you are supplying mismatched arguments for conversion
specifiers in the above calls, which invokes undefined behaviour. A
cast to int would resolve the UB, but it's better to cast size_t
arguments to unsigned int or unsigned long.

    bpp=malloc(sizeof(BEAM_PROFILE));

If you do:

  bpp = malloc(sizeof *bpp);

then the code remains correct even if later the base type of bpp is
changed.

    lpp=(unsigned long)bpp;

    printf("Memory was allocated at address(X mod.) %.8X\n", bpp);

You mean to supply lpp here, I'm sure.

    printf("Memory was allocated at address(p mod.) %p\n", bpp);

The 'p' conversion specifier needs the corresponding argument to be a
void*. So a cast is, strictly speaking, necessary.

    bpp=malloc(sizeof(BEAM_PROFILE));
    printf("Size of the pointer is %d\n", sizeof(bpp));
    lpp=(unsigned long)bpp;

What is the intent behind assigning to lpp if you never use it further?



    printf("Memory was allocated at address %.8X\n", bpp);
    printf("Memory was allocated at address(p mod.) %p\n", bpp);

}

///////////////////////////////////////////////////////////////////////////////////

The result, using the Large memory model, is the following:

C:\PACIFICO\SRC>tstmall
sizeof(*BEAM_PROFILE) is 4
sizeof(lpp) is 4
Memory was allocated at address(X mod.) 00000004
Memory was allocated at address(p mod.) 1DD5:0004
Size of the pointer is 4
Memory was allocated at address 00000004
Memory was allocated at address(p mod.) 1DD6:0004

This is the danger of treating pointers as compatible with integers. For
most modern flat model machines a pointer is just an integer, but such
a relation is not guaranteed. As you have found, under segmented memory
architectures, a pointer is usually of two components and merely
casting one to an integer does not yield the full address, but the
offset part alone.



With the small one, instead, I have the following

C:\PACIFICO\SRC>tstmall
sizeof(*BEAM_PROFILE) is 2
sizeof(lpp) is 4
Memory was allocated at address(X mod.) 00000672
Memory was allocated at address(p mod.) 0672
Size of the pointer is 2
Memory was allocated at address 0000067C
Memory was allocated at address(p mod.) 067C

So now things seem to work fine for the both of them. Now I am just
wondering why it takes to different segments to allocate a structure
which is only four bytes long, but i guess this has something to do
with the memory management model of the compiler...

That's an implementation decision. Under the x86 segmented memory model,
a segment can begin at any "paragraph boundary", which is any address
that is a multiple of 16. Segments do not have a minimum size and they
can perfectly overlap. Your compiler has merely chosen to place the
second BEAM_PROFILE object on the next higher segment address, instead
of at a higher offset within the same segment.

<snip>

.



Relevant Pages

  • [PATCH] bigphysarea for 2.6.10 en 2.6.11
    ... +contineous memory for the entire runtime of Linux. ... +The big physical area is mainly managed by two functions. ... +caddr_t bigphysarea_alloc_pages(int count, int align, int priority) ... second it is not possible to allocate some memory ...
    (Linux-Kernel)
  • Re: Initial values of File scoped and Block level variables
    ... the loaderallocates data segment ... If T is a function type, any initialization ... >that informs the loader to allocate 1 element of sizeofmemory. ...
    (comp.lang.c)
  • Re: Weird malloc behaviour
    ... The result, using the Large memory model, is the following: ... wondering why it takes to different segments to allocate a structure ... second BEAM_PROFILE object on the next higher segment address, ...
    (comp.lang.c)
  • [PATCH] bigphysarea for 2.6.9
    ... +contineous memory for the entire runtime of Linux. ... +caddr_t bigphysarea_alloc_pages(int count, int align, int priority) ... second it is not possible to allocate some memory ... * This program is free software; you can redistribute it and/or modify ...
    (Linux-Kernel)
  • Re: NULL with representation other then all bits 0
    ... >> process id, segment id, page id, page offset, and bit or byte. ... trying to allocate stuff in memory becomes sort of a 3-dimensional ... >and wanted to address it in a C program with a pointer, ...
    (comp.lang.c)