inet_ntoa 缓存的坑

99 阅读1分钟

问题

  • 先来看一段代码
 #include <stdio.h>
 #include <string.h>
 #include <arpa/inet.h>  // For inet_ntoa and in_addr

 int main() {
     struct in_addr addr1, addr2;

     // 两个IP地址的网络字节序表示(例如:192.168.1.1 和 10.0.0.1)
     addr1.s_addr = inet_addr("192.168.1.1");
     addr2.s_addr = inet_addr("10.0.0.1");

     // 第一次调用 inet_ntoa
     char *ip_str1 = inet_ntoa(addr1);

     // 第二次调用 inet_ntoa
     char *ip_str2 = inet_ntoa(addr2);

     printf("First IP: %s\n", ip_str1);
     printf("Second IP: %s\n", ip_str2);

     return 0;
 }
  • 代码的输出结果

    1726800951313.png

  • ip_str1的值被ip_str2覆盖了

原因

  • 先看一下inet_ntoa的源码
/* Convert Inet number to ASCII representation.
  Copyright (C) 1997-2018 Free Software Foundation, Inc.
  This file is part of the GNU C Library.
  Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.

  The GNU C Library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  The GNU C Library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with the GNU C Library; if not, see
  <http://www.gnu.org/licenses/>.  */

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>

/* The interface of this function is completely stupid, it requires a
  static buffer.  We relax this a bit in that we allow one buffer for
  each thread.  */
static __thread char buffer[18];


char *
inet_ntoa (struct in_addr in)
{
 unsigned char *bytes = (unsigned char *) &in;
 __snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",
         bytes[0], bytes[1], bytes[2], bytes[3]);

 return buffer;
}

可以看到,因为存储inet_ntoa的地址是_thread全局的线程变量,第一次调用inet_ntoa后,需要把结果缓存起来