malloc pointer address in main and in other functi

2019-08-09 03:12发布

This question already has an answer here:

I have the following question. Why is there a difference in the addresses of the two pointers in following example? This is the full code:

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

void *mymalloc(size_t bytes){
void * ptr = malloc(bytes);
printf("Address1 = %zx\n",(size_t)&ptr);
return ptr;
}

void main (void)
{
unsigned char *bitv =  mymalloc(5);
printf("Address2 = %zx\n",(size_t)&bitv);
}

Result:

Address1 = 7ffe150307f0
Address2 = 7ffe15030810

4条回答
够拽才男人
2楼-- · 2019-08-09 03:47

In your code you used to print pointer's address following code:

printf("%zx", (size_t)&p);

It doesn't print address of variabele it's pointing to, it prints address of pointer.

You could print address using '%p' format:

printf("%p", &n); // PRINTS ADDRESS OF 'n'

There's an example which explains printing addresses

int n;
int *v;

n = 54;
v = &n;

printf("%p", v); // PRINTS ADDRESS OF 'n' 
printf("%p", &v); // PRINTS ADDRESS OF pointer 'v'
printf("%p", &n); // PRINTS ADDRESS OF 'n'
printf("%d", *v); // PRINTS VALUE OF 'n'
printf("%d", n); // PRINTS VALUE OF 'n'

So your code should be written like this:

void * get_mem(int size)
{
     void * buff = malloc(size); // allocation of memory
     // buff is pointing to result of malloc(size)
     if (!buff) return NULL; //when malloc returns NULL end function
     //else print address of pointer
     printf("ADDRESS->%p\n", buff);
     return buff;
}

int main(void)
{
    void * buff = get_mem(54);
    printf("ADDRESS->%p\n", buff);
    free(buff);
    return 0;
}
查看更多
我想做一个坏孩纸
3楼-- · 2019-08-09 03:47

(In addition to other answers, which you would read first and probably should help you more ...)

Read a good C programming book. Pointers and addresses are very difficult to explain, and I'm not even trying to. So the address of a pointer &ptr is generally not the same as the value of a pointer (however, you could code ptr= &ptr; but you often don't want to do that)... Look also at the picture explaining virtual address space.

Then read more documentation about malloc: malloc(3) Linux man page, this reference documentation, etc... Here is fast, standard conforming, but disappointing implementation of malloc.

read also documentation about printf: printf(3) man page, printf reference, etc... It should mention %p for printing pointers...

Notice that you don't print a pointer (see Alk's answer), you don't even print its address (of an automatic variable on the call stack), you print some cast to size_t (which might not have the same bit width as a pointer, even if on my Linux/x86-64 it does).

Read also more about C dynamic memory allocation and about pointer aliasing.

At last, read the C11 standard specification n1570.

(I can't believe why you would expect the two outputs to be the same; actually it could happen if a compiler is optimizing the call to mymalloc by inlining a tail call)

So I did not expect the output to be the same in general. However, with gcc -O2 antonis.c -o antonis I've got (with a tiny modification of your code)....

a surprise

However, if you declare the first void *mymalloc(size_t bytes) as a static void*mymalloc(size_t bytes) and compile with GCC 7 on Linux/Debian/x86-64 with optimizations enabled, you do get the same output; because the compiler inlined the call and used the same location for bitv and ptr; here is the generated assembler code with gcc -S -O2 -fverbose-asm antonis.c:

    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "Address1 = %zx\n"
.LC1:
    .string "Address2 = %zx\n"
    .section    .text.startup,"ax",@progbits
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB22:
    .cfi_startproc
    pushq   %rbx    #
    .cfi_def_cfa_offset 16
    .cfi_offset 3, -16
# antonis.c:5: void * ptr = malloc(bytes);
    movl    $5, %edi    #,
# antonis.c:11: {
    subq    $16, %rsp   #,
    .cfi_def_cfa_offset 32
# antonis.c:6: printf("Address1 = %zx\n",(size_t)&ptr);
    leaq    8(%rsp), %rbx   #, tmp92
# antonis.c:5: void * ptr = malloc(bytes);
    call    malloc@PLT  #
# antonis.c:6: printf("Address1 = %zx\n",(size_t)&ptr);
    leaq    .LC0(%rip), %rdi    #,
# antonis.c:5: void * ptr = malloc(bytes);
    movq    %rax, 8(%rsp)   # tmp91, ptr
# antonis.c:6: printf("Address1 = %zx\n",(size_t)&ptr);
    movq    %rbx, %rsi  # tmp92,
    xorl    %eax, %eax  #
    call    printf@PLT  #
# antonis.c:13: printf("Address2 = %zx\n",(size_t)&bitv);
    leaq    .LC1(%rip), %rdi    #,
    movq    %rbx, %rsi  # tmp92,
    xorl    %eax, %eax  #
    call    printf@PLT  #
# antonis.c:14: }
    addq    $16, %rsp   #,
    .cfi_def_cfa_offset 16
    popq    %rbx    #
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE22:
    .size   main, .-main

BTW, if I compile your unmodified source (without static) with gcc -fwhole-program -O2 -S -fverbose-asm I'm getting the same assembler as above. If you don't add static and don't compile with -fwhole-program the two Adddress1 and Address2 stay different.


two run outputs

I run that antonis executable and got on the first time:

/tmp$ ./antonis
Address1 = 7ffe2b07c148
Address2 = 7ffe2b07c148

and the second time:

/tmp$ ./antonis
Address1 = 7ffc441851a8
Address2 = 7ffc441851a8

If you want to guess why the outputs are different from one run to the next one, think of ASLR.

BTW, a very important notion when coding in C is that of undefined behavior (see also this and that answers and the references I gave there). You don't have any in your question (it is just unspecified behavior), but as my contrived answer shows, you should not expect a particular behavior in that precise case.

PS. I believe (but I am not entirely sure) that a standard conforming C implementation could output Address1= hello world and likewise for Address2. After all, the behavior of printf with %p is implementation defined. And surely you could get 0xdeadbeef for both. More seriously, an address is not always the same (of the same bitwidth) than a size_t or an int, and the standard defines intptr_t in <stdint.h>

查看更多
淡お忘
4楼-- · 2019-08-09 03:49

It's because you are printing the address of the pointer variable, not the pointer. Remove the ampersand (&) from bitv and ptr in your printfs.

printf("Address1 = %zx\n",(size_t)ptr);

and

printf("Address2 = %zx\n",(size_t)bitv);

Also, use %p for pointers (and then don't cast to size_t)

WHY?

In this line of code:

 unsigned char *bitv =  mymalloc(5);

bitv is a pointer and its value is the address of the newly allocated block of memory. But that address also needs to be stored, and &bitv is the address of the where that value is stored. If you have two variables storing the same pointer, they will still each have their own address, which is why &ptr and &bitv have different values.

But, as you expected, ptr and bitv will have the same value when you change your code.

查看更多
Bombasti
5楼-- · 2019-08-09 03:49

Why is there a difference in the addresses of the two pointers

Because the two pointers are two different pointer(-variable)s, each having it's own address.

The value those two pointer(-variable)s carry in fact are the same.

To prove this print their value (and not their address) by changing:

  printf("Address1 = %zx\n",(size_t)&ptr);

to be

  printf("Address1 = %p\n", (void*) ptr);

and

  printf("Address2 = %zx\n",(size_t)&bitv);

to be

  printf("Address2 = %p\n", (void*) bitv);
查看更多
登录 后发表回答