开发者

When returning a pointer to a local array why is it always the same value?

I am programming a simple packet sniffer for a class project. For a little while, I ran into the issue where the source and destination of a packet appeared to be the same. For example, the source and destination of an Ethernet frame would be the same MAC address all of the time. I custom-made ether_ntoa(char *) because Windows does not seem to have ethernet.h like Linux does. Code snippet is below:

char *ether_ntoa(u_char etheraddr[ETHER_ADDR_LEN])
{
    int i, j;
    char eout[32];

    for(i = 0, j = 0; i < 5; i++)
    {
  开发者_高级运维      eout[j++] = etheraddr[i] >> 4;
        eout[j++] = etheraddr[i] & 0xF;
        eout[j++] = ':';
    }
    eout[j++] = etheraddr[i] >> 4;
    eout[j++] = etheraddr[i] & 0xF;
    eout[j++] = '\0';
    for(i = 0; i < 17; i++)
    {
        if(eout[i] < 10)
            eout[i] += 0x30;
        else if(eout[i] < 16)
            eout[i] += 0x57;
    }
    return(eout);
}

I solved the problem by using malloc() to have the compiler assign memory (i.e. instead of char eout[32], I used char * eout; eout = (char *) malloc (32);). However, I thought that the compiler assigned different memory locations when one sized a char-array at compile time. Is this incorrect?


As others have pointed out, you can't return a pointer to an object with automatic storage duration - when eout goes out of scope, it no longer exists. GCC actually warns you about this:

ether_ntoa.c: In function ‘ether_ntoa’:
ether_ntoa.c:26: warning: function returns address of local variable

The usual way to achieve the desired result is to have the caller responsible for allocating the destination. For example:

int ether_ntoa(unsigned char etheraddr[ETHER_ADDR_LEN], char *dest, size_t len)
{
    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
        (unsigned)etheraddr[0],
        (unsigned)etheraddr[1],
        (unsigned)etheraddr[2],
        (unsigned)etheraddr[3],
        (unsigned)etheraddr[4],
        (unsigned)etheraddr[5]);
}

(Note also that your handcoded conversion routine can be replaced with a simple snprintf() call). You'd call it like so:

char eout[32];
ether_ntoa(etheraddr, eout, sizeof eout);
/* Converted address is now in eout */

The ether_ntoa() function on Linux uses a different approach - it declares the buffer in the function as static. If you did that, then your eout would live for the life of the program, so you can return a pointer to it. The downside is that there is only one eout - each time you call ether_ntoa, it will overwrite the previous one.


the problem with the former way is that conceptually incorrect you couldnt return a pointer to a local variable, bc local variables lives on stack you have two aproachs 1) pass by parameter the buffer (eout) and its size, and then populate it inside the function 2) allocate the buffer (eout) inside the function, a give the invoquer the responsability to deallocate the buffer once its done with it. regards


Your problem was that when you declare char eout[32] inside a function, the memory allocated to that array is on the stack. After your function returns, the stack frame is popped, and the memory address formerly assigned to the array can be reassigned to other stack variables. As you have figured out yourself, the proper way to fix it is to malloc() the space for the array so that it persists after the function returns.


Just remember to free() your array after you are done so you don't have a memory leak. If you are using C++, you can use boost::shared_array instead so you don't have to manually free the memory. http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_array.htm

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜