1

I am trying to get Mac address by this code:

void getMacAdress(unsigned char **address)
{
    int s;
    struct ifreq buffer;

    s = socket(PF_INET, SOCK_DGRAM, 0);
    memset(&buffer, 0x00, sizeof(buffer));
    strcpy(buffer.ifr_name, "eth0");
    ioctl(s, SIOCGIFHWADDR, &buffer);
    close(s);
    *address = (unsigned char *)buffer.ifr_hwaddr.sa_data;

    for (s = 0; s < 6; s++)
    {
        printf("%.2X ", *(*address + s));
    }

    printf("\n");
}

int main(int argc, char *argv[])
{
    unsigned char *address;

    getMacAdress(&address);
    int i;

    for (i = 0; i < 6; i++)
    {
        printf("%.2X ", *(address + i));
    }

    printf("\n");
    return 0;
}

I got a correct result as

08 00 27 0A 4E 98 
08 00 27 0A 4E 98

but when I delete printf snippet code in getMacAddress() function it becomes:

void getMacAdress(unsigned char **address)
{
    int s;
    struct ifreq buffer;

    s = socket(PF_INET, SOCK_DGRAM, 0);
    memset(&buffer, 0x00, sizeof(buffer));
    strcpy(buffer.ifr_name, "eth0");
    ioctl(s, SIOCGIFHWADDR, &buffer);
    close(s);
    *address = (unsigned char *)buffer.ifr_hwaddr.sa_data;
    printf("\n");
}

I got the wrong result

08 00 00 00 00 00

Can you explain to me why that is and how I can solve this problem?

4
  • Why are you passing a "pointer to pointer to char"? Commented Jun 30, 2015 at 2:32
  • 4
    I think the pointer you write into your var gets invalidated as soon as you exit the function, since your buffer is on the stack. Commented Jun 30, 2015 at 2:33
  • 2
    You copy a pointer to a local variable in getMacAdress() into the address passed into it from main(), and that leads to undefined behaviour. The space is reused and you get what you get (and you're lucky you didn't crash). Commented Jun 30, 2015 at 2:33
  • 2
    malloc some memory to *address and strcpy (*address , buffer.ifr_hwaddr.sa_data) Commented Jun 30, 2015 at 2:36

3 Answers 3

3

Problem is here:

*address = (unsigned char *)buffer.ifr_hwaddr.sa_data;

buffer is a local variable to your function. So the pointer you are storing in address points to a local variable which is destroyed when the function returns, leaving a dangling pointer.

Trying to read from this pointer causes undefined behaviour. Your output can be explained depending on whether the memory was re-used for something else already by the time you did the print or not.

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, i understand but why the adding printf function in getMacAdress() leads to getting a true result?
@Sam Deferencing an out-of-scope local pointer is undefined behavior, meaning anything could happen. Calling printf just happens to trigger some behind-the-scenes quackery that changed the nature of the undefined behavior.
It's just luck. By chance, the old data was not overwritten by stack pushes. Your memory pointed to by address was kind of in limbo. It was set up to be freed but nothing overwrote it yet because not much else used the stack.
@Sam yeah, it helps to think of it like you're building an apartment with a bunch of stories, and on the 2nd floor someone wrote a book and left the only copy there. When the getMacAddress function exists the 2nd floor is marked condemned, but everything stays put until you call additional functions in main. What happens when you get lucky is that that printf in main happens upon that book and prints it, even though other things on that floor might have been replaced with walls or in this case space for int i and the associated calls to printf
2

If you want to fix it...

//*address = (unsigned char *)buffer.ifr_hwaddr.sa_data;
*address = malloc (strlen (buffer.ifr_hwaddr.sa_data) + 1);
strcpy (*address, buffer.ifr_hwaddr.sa_data);

Comments

1

you cannot point to a stack space to return in a function.

Instead, you can malloc a heap space to store the result you wanted:

void getMacAdress(unsigned char **address)
{
    int s;
    struct ifreq buffer;

    s = socket(PF_INET, SOCK_DGRAM, 0);
    memset(&buffer, 0x00, sizeof(buffer));
    strcpy(buffer.ifr_name, "eth0");
    ioctl(s, SIOCGIFHWADDR, &buffer);
    close(s);
    *address = (unsigned char*) malloc(sizeof(buffer.ifr_hwaddr.sa_data));
    memcpy(*address, buffer.ifr_hwaddr.sa_data,sizeof(buffer.ifr_hwaddr.sa_data));

    //for (s = 0; s < 6; s++)
    //{
    //    printf("%.2X ", *(*address + s));
    //}

    //printf("\n");
}

BTW, don't forget to free the heap space in your main function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.