1. 程式人生 > >linux程式設計獲取本機網路相關引數

linux程式設計獲取本機網路相關引數

LINUX下的getifaddrs()函式的記憶體釋放問題 
在LINUX下獲取網絡卡資訊需要用到IOCTL或者getifaddrs 
而我在用getifaddrs的時候遇到了記憶體方面的問題 

先看相關定義: 
========== 

函式定義: 
/* Create a linked list of `struct ifaddrs' structures, one for each 
   network interface on the host machine.  If successful, store the 
   list in *IFAP and return 0.  On errors, return -1 and set `errno'. 

   The storage returned in *IFAP is allocated dynamically and can 
   only be properly freed by passing it to `freeifaddrs'.  */ 
extern int getifaddrs (struct ifaddrs **__ifap) __THROW; 

/* Reclaim the storage allocated by a previous `getifaddrs' call.  */ 
extern void freeifaddrs (struct ifaddrs *__ifa)  __THROW; 
============== 
此函式需要的結構體定義: 

struct ifaddrs 

  struct ifaddrs *ifa_next;     /* Pointer to the next structure.  */ 

  char *ifa_name;               /* Name of this network interface.  */ 
  unsigned int ifa_flags;       /* Flags as from SIOCGIFFLAGS ioctl.  */ 

  struct sockaddr *ifa_addr;    /* Network address of this interface.  */ 
  struct sockaddr *ifa_netmask; /* Netmask of this interface.  */ 
  union 
  { 
    /* At most one of the following two is valid.  If the IFF_BROADCAST 
       bit is set in `ifa_flags', then `ifa_broadaddr' is valid.  If the 
       IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid. 
       It is never the case that both these bits are set at once.  */ 
    struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */ 
    struct sockaddr *ifu_dstaddr; /* Point-to-point destination address.  */ 
  } ifa_ifu; 
  /* These very same macros are defined by <net/if.h> for `struct ifaddr'. 
     So if they are defined already, the existing definitions will be fine.  */ 
# ifndef ifa_broadaddr 
#  define ifa_broadaddr ifa_ifu.ifu_broadaddr 
# endif 
# ifndef ifa_dstaddr 
#  define ifa_dstaddr   ifa_ifu.ifu_dstaddr 
# endif 

  void *ifa_data;               /* Address-specific data (may be unused).  */ 
}; 
============= 
我在呼叫了getifaddrs()之後,正常地完成了需要的工作 
但是最後如果用freeifaddrs,則出現執行時錯誤 
*** glibc detected *** d: free(): invalid pointer: 0x0804a4d4 *** 
======= Backtrace: ========= 
/lib/libc.so.6[0xb7eda911] 
/lib/libc.so.6(__libc_free+0x84)[0xb7edbf84] 
/lib/libc.so.6(freeifaddrs+0x1d)[0xb7f512dd] 
d[0x8048989] 
d[0x80486a5] 
/lib/libc.so.6(__libc_start_main+0xdc)[0xb7e8c87c] 
d[0x8048491] 
======= Memory map: ======== 
08048000-08049000 r-xp 00000000 03:07 48637 /home/souldump/bin/d 
08049000-0804a000 rw-p 00000000 03:07 48637 /home/souldump/bin/d 
0804a000-0806b000 rw-p 0804a000 00:00 0 [heap] 
b7d00000-b7d21000 rw-p b7d00000 00:00 0 
b7d21000-b7e00000 ---p b7d21000 00:00 0 
b7e76000-b7e77000 rw-p b7e76000 00:00 0 
b7e77000-b7f90000 r-xp 00000000 03:05 16184 /lib/libc-2.4.so 
b7f90000-b7f92000 r--p 00118000 03:05 16184 /lib/libc-2.4.so 
b7f92000-b7f94000 rw-p 0011a000 03:05 16184 /lib/libc-2.4.so 
b7f94000-b7f98000 rw-p b7f94000 00:00 0 
b7fab000-b7fb5000 r-xp 00000000 03:05 20108 /lib/libgcc_s.so.1 
b7fb5000-b7fb6000 rw-p 00009000 03:05 20108 /lib/libgcc_s.so.1 
b7fb6000-b7fb7000 rw-p b7fb6000 00:00 0 
b7fb7000-b7fd1000 r-xp 00000000 03:05 16177 /lib/ld-2.4.so 
b7fd1000-b7fd3000 rw-p 00019000 03:05 16177 /lib/ld-2.4.so 
bfb2b000-bfb41000 rw-p bfb2b000 00:00 0 [stack] 
ffffe000-fffff000 ---p 00000000 00:00 0 [vdso] 

實際上也有人出現相同問題: 
http://p.g.yupoo.com/nph-proxy.cgi/000110A/http/www.linuxdby.com/bbs/viewthread.php=3ftid=3d10756 
此人說:"這說明不是真正的連結串列,指標非法" 
但是又沒有進一步說明怎麼解決 
他乾脆沒有呼叫freeifaddrs,自然會記憶體洩漏..... 

我去看了afaddrs.c 
freeifaddrs的定義居然是: 
void 
freeifaddrs (struct ifaddrs *ifa) 

free (ifa); 

怎麼樣,很囧吧,明明在標頭檔案裡說"必須用freeifaddrs才能正確free..." 
然後我看了一下getifaddrs的函式體 

他在getifaddrs內部定義了一個結構 
struct ifaddrs_storage 

struct ifaddrs ifa; 
union 

/* Save space for the biggest of the four used sockaddr types and 
avoid a lot of casts. */ 
struct sockaddr sa; 
struct sockaddr_ll sl; 
struct sockaddr_in s4; 
struct sockaddr_in6 s6; 
} addr, netmask, broadaddr; 
char name[IF_NAMESIZE + 1]; 
}; 

然後把獲取的各網絡卡資訊一個個填充到此結構的struct ifaddrs ifa中,ifa的next值手動設定為下一個struct ifaddrs_storage中的ifa的地址... 
這酒是所謂的"偽連結串列"吧? 
這就是我無法正確free掉它的原因? 
我究竟要怎麼把它free掉?freeifaddrs一執行就執行時錯誤 




LINUX取得本機IP的簡單C程式 
注意這裡用了兩個struct ifaddrs 



//程式碼根據UNP和man手冊編寫 
//適用於LINUX/BSD(FreeBSD, MacOS X) 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 

#include <sys/types.h> 
#include <sys/socket.h> 

#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <ifaddrs.h> 

int main(void) 

        struct ifaddrs        *ifc, *ifc1; 
        char                ip[64]; 
        char                nm[64]; 

        if (0 != getifaddrs(&ifc)) return(-1); 
        ifc1 = ifc; 

        printf("Iface\tIP address\tNetmask\n"); 
        for(; NULL != ifc; ifc = (*ifc).ifa_next) { 
                printf("%s", (*ifc).ifa_name); 
                if (NULL != (*ifc).ifa_addr) { 
                        inet_ntop(AF_INET, &(((struct sockaddr_in*)((*ifc).ifa_addr))->sin_addr), ip, 64); 
                        printf("\t%s", ip); 
                } else { 
                        printf("\t\t"); 
                } 
                if (NULL != (*ifc).ifa_netmask) { 
                        inet_ntop(AF_INET, &(((struct sockaddr_in*)((*ifc).ifa_netmask))->sin_addr), nm, 64); 
                        printf("\t%s", nm); 
                } else { 
                        printf("\t\t"); 
                } 
                printf("\n"); 
        } 

        freeifaddrs(ifc1); 
        return(0); 




-------------------------------------------------------------------------------- 



============原來的============ 
struct ifaddrs *ifap, *ifaphead, *ifaTmp; 
getifaddrs(&ifap); 
ifaphead = ifap; 
while((ifapTmp = ifap) != NULL) 

//實際任務程式碼  
ifap = ifapTmp->ifa_next; 

freeifaddrs(ifaphead); 
=========修改後======== 
struct ifaddrs *ifap, *ifaphead; 
getifaddrs(&ifap); 
ifaphead = ifap; 
while(ifap != NULL) 

//實際任務程式碼  
ifap = ifa_next; 

freeifaddrs(ifaphead); 
================== 
僅僅是用了一個ifapTmp來代替ifap做事,區別僅此而已(而且我也忘了一開始為什麼要用ifapTmp....) 
但是最後都是用了freeifaddrs(ifaphead)啊,並沒有傳錯指標啊???? 
中間的程式碼並沒有對這段資料做任何修改啊..... 

請指教一下,這唯一的區別為什麼會造成我原先的程式碼freeifaddrs失敗?謝謝! 



ifaphead = ifap;                                //這裡用ifaphead儲存ifap指標地址 
while((ifapTmp = ifap) != NULL) 

ifap = ifapTmp->ifa_next;                //這裡修改了ifap的地址 

freeifaddrs(ifaphead);                       //由於ifap的地址修改,所以ifaphead已經是無效指標。 

相關推薦

linux程式設計獲取網路相關引數

LINUX下的getifaddrs()函式的記憶體釋放問題 在LINUX下獲取網絡卡資訊需要用到IOCTL或者getifaddrs 而我在用getifaddrs的時候遇到了記憶體方面的問題 先看相關定義: ========== 函式定義: /* Create a linked list of `struct

linux程式設計獲取網絡卡資訊

轉自:https://blog.csdn.net/shaderdx/article/details/78403437 ifaddrs結構體定義如下: struct ifaddrs    {      &

linux程式設計獲取IP地址的三種方法

                這是一項不太清晰而且沒有多大意義的工作。一個原因是網路地址的設定非常靈活而且都是允許使用者進行個性

linux獲取IPv6地址、字首、閘道器

獲取本機IPv6資訊命令:cat /proc/net/if_inet6 [email protected]:/home/user1/# cat /proc/net/if_inet6 fe80000000000000922b34fffe4e70f4 02 40 20 80 et

C#獲取串列埠引數(適合初學者參考)

在C#中實現串列埠相比VC下容易很多,只要在工具欄中拖一個串列埠控制元件,設定好串列埠號即可開始工作。 如果是在後臺執行串列埠通訊,那麼簡單的設定已經足夠了。 當然,我們如果想讓這個串列埠有比較友好的介面設定那麼,我們在實現的時候,往往需要把介面上增加一些串列埠屬性引數的設定框。 一、串

linux c 獲取ip地址

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <

Java 核心程式設計-------獲取域名和主機名

package GetCanonical; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.

snmp獲取網路流量

本文對使用snmp工具取得伺服器/交換機的網口的流量情況進行了簡單的總結,前提是系統的snmp服務端已經在正常工作且能接受操作端的查詢。 取得所有網/埠的描述 snmpwalk -v 2c -c public ipaddr ifDescr cisco交換機埠流量取值需要注意的

SOCKET 程式設計 獲取IP 地址

源程式: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #

Linux下C程式設計實現---獲取IP地址

在LINUX下,如果需要獲取本機的IP地址,需要用到以下一個結構體,該結構體在/usr/include/net/if.h檔案中 struct ifreq { # define IFHWADDRLEN 6 # define IFNAMSIZ IF_

Linux雲主機獲取公網IP地址

forever linux ip地址 主機 因為公司的雲主機使用ifconfig和ip add命令都只能看到內網IP地址,而腳本裏面又需要獲取公網IP地址進行一些動作;# ip ad 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc

linux 獲取MAC/IP地址的方法

linunx 編程 mac 地址功能:查詢本機IP/MAC地址,過濾掉127.0.0.1 loop-back 地址適用:linux, ubuntu 16.04 調試通過#include <stdlib.h>#include <stdio.h>#include <unistd.h&

獲取IP(適用於Linux系統)

tex cat 獲取本機 smo cal network enum print inet6 獲取本機IP(適用於Linux系統) /** * @desc 獲取本機IP(適用於Linux系統) * @return Ip */ public static String getL

Linux 編程獲取所有網卡和IP

ring lin char net div har return arpa free #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <

Linux下C語言獲取IP地址

#include <sys/ioctl.h> #include <net/if.h> #include <arpa/inet.h>   char* GetLocalIp() { int MA

Linux 獲取IP、MAC地址用法大全

getifaddrs()和struct ifaddrs的使用,獲取本機IP     ifaddrs結構體定義如下: struct ifaddrs { struct ifaddrs *ifa_next; /* Next item in

使用Linux curl命令獲取公網IP地址

使用Linux curl命令獲取本機公共IP地址   在本教程中,我們將學習如何使用Linux curl命令查詢計算機的公共IP地址。 通常,如果我們想要找到我們使用的公共IP地址,我們會去谷歌並搜尋“我的IP地址是什麼”。但是如果使用Linux,則可以使用curl命令從命令列

獲取中python模組相關資訊

不同於 C++、Java、C# namespace 僅作為符號隔離字首,Python 模組是執行期物件。模組對應同名原始碼檔案,為成員提供全域性名字空間。 模組物件 模組物件有幾個重要屬性: name: 模組名 .,在 sys.modules 中以此為主鍵。 fil

網路應用】批處理獲取的公網IP地址

【方案一】BAT + VBS @echo off set "URL=http://www.ip138.com/ip2city.asp" >%temp%/download.vbs echo Set objDOM = WScript.GetObject(WScript.A

Linux下靠譜的獲取IP的C程式碼實

這裡寫程式碼片http://blog.csdn.net/langeldep/article/details/8306603 正在做一個網路程式設計的任務,多臺裝置向伺服器傳送圖片,傳送圖片的時候同時告訴伺服器自己的IP。伺服器根據IP來區分不同的裝置,將圖片存