当返回指向本地数组的指针时,为啥它总是相同的值?
Posted
技术标签:
【中文标题】当返回指向本地数组的指针时,为啥它总是相同的值?【英文标题】:When returning a pointer to a local array why is it always the same value?当返回指向本地数组的指针时,为什么它总是相同的值? 【发布时间】:2010-04-07 22:50:08 【问题描述】:我正在为一个班级项目编写一个简单的数据包嗅探器。有一段时间,我遇到了一个数据包的来源和目的地似乎相同的问题。例如,以太网帧的源和目标将始终是相同的 MAC 地址。我定制了ether_ntoa(char *)
,因为Windows 似乎没有像Linux 那样的ethernet.h
。代码sn-p如下:
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);
我通过使用malloc()
让编译器分配内存(即我使用char * eout; eout = (char *) malloc (32);
而不是char eout[32]
)解决了这个问题。但是,我认为当在编译时调整 char 数组的大小时,编译器会分配不同的内存位置。这是不正确的吗?
【问题讨论】:
你能澄清一下你面临的问题吗 听起来像是内存泄漏。更好的设计是让调用者分配一个缓冲区,它将连同缓冲区的大小一起传递给您的自定义函数。 【参考方案1】:正如其他人指出的那样,您不能返回指向具有自动存储持续时间的对象的指针 - 当eout
超出范围时,它不再存在。 GCC 实际上会警告您:
ether_ntoa.c: In function ‘ether_ntoa’:
ether_ntoa.c:26: warning: function returns address of local variable
达到预期结果的常用方法是让调用者负责分配目的地。例如:
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]);
(另请注意,您的手动编码转换例程可以替换为简单的snprintf()
调用)。你可以这样称呼它:
char eout[32];
ether_ntoa(etheraddr, eout, sizeof eout);
/* Converted address is now in eout */
Linux 上的ether_ntoa()
函数使用不同的方法——它将函数中的缓冲区声明为static
。如果你这样做了,那么你的eout
将在程序的生命周期内存在,所以你可以返回一个指向它的指针。缺点是只有一个eout
——每次调用ether_ntoa
,都会覆盖之前的。
【讨论】:
【参考方案2】:前一种方式的问题是概念上不正确 您无法返回指向局部变量的指针,bc 局部变量存在于堆栈中 你有两种方法 1)通过参数传递缓冲区(eout)及其大小,然后将其填充到函数内部 2)在函数内部分配缓冲区(eout),让调用者有责任在缓冲区完成后解除分配。 问候
【讨论】:
【参考方案3】:您的问题是,当您在函数内声明 char eout[32]
时,分配给该数组的内存在堆栈上。在你的函数返回后,堆栈帧被弹出,之前分配给数组的内存地址可以重新分配给其他堆栈变量。正如您自己发现的那样,修复它的正确方法是 malloc()
数组的空间,以便在函数返回后它仍然存在。
【讨论】:
【参考方案4】:请记住在完成后free()您的数组,这样您就不会发生内存泄漏。如果您使用的是 C++,则可以使用 boost::shared_array 代替,这样您就不必手动释放内存。 http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_array.htm
【讨论】:
以上是关于当返回指向本地数组的指针时,为啥它总是相同的值?的主要内容,如果未能解决你的问题,请参考以下文章
当函数返回时,指向超出范围的对象的 C++ 指针 - 为啥会这样?
C语言基础:指针相关概念(指针的算术运算 指针数组指向指针的指针 传递指针给函数 从函数返回指针 )为啥C 语言不支持在调用函数时返回局部变量的地址?