深入理解C指针之五(指针的安全问题)--By kmalloc

本文深入探讨了指针在编程中的安全问题,通过实例展示了不当使用指针可能导致的数据破坏和崩溃性错误。强调了在访问数组、进行强制类型转换以及使用指针时,程序员必须明确指针指向的位置的重要性。

-------------------------------------------指针的安全问题(重点)-------------------------------------


  例9
char s='a';                           
int *ptr; 
ptr=(int*)&s; 
*ptr=1298 
指针ptr是一个int*类型的指针,它指向的类型是int。它指向的地址就是s的首地址。在32位程序中,s占一个字节,int类型占四个字节。最后一条语句不但改变了s所占的一个字节,还把和s相临的高地址方向的三个字节也改变了。这三个字节是干什么的?只有编译程序知道,而写程序的人是不太可能知道的。也许这三个字节里存储了非常重要的数据,也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,这三个字节的值被改变了!这会造成崩溃性的错误。 


  让我们再来看一例: 
  例10 
  1char a; 
  2int *ptr= &a; 
  ... 
  ... 
  3ptr++; 
  4*ptr=115; 
  该例子完全可以通过编译,并能执行。但是看到没有?第3句对指针ptr进行自加1运算后,ptr指向了和整形变量a相邻的高地址方向的一块存储区。这块存储区里是什么?我们不知道。有可能它是一个非常重要的数据,甚至可能是一条代码。而第4句竟然往这片存储区里写入一个数据!这是严重的错误。所以在使用指针时,程序员心里必须非常清楚:我的指针究竟指向了哪里。在用指针访问数组的时候,也要注意不要超出数组的低端和高端界限,否则也会造成类似的错误。 
在指针的强制类型转换:ptr1=(TYPE*)ptr2中,如果sizeof(ptr2的类型)大于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是不安全的。至于为什么,读者结合例9来想一想,应该会明白的。

转载于:https://www.cnblogs.com/qinkai/archive/2012/09/21/2697402.html

非常棒的题目!这个题目要求你使用 Linux 内核提供的 `list.h` 链表接口,实现一个带有 MAC 和 IPv4 地址的有序链表,并提供增删查的完整接口。 --- ## ✅ 题目目标简述 你将完成以下任务: 1. 使用 `struct list_head` 实现一个链表。 2. 每个节点包含一个 MAC 地址(6 字节)和一个 IPv4 地址(4 字节)。 3. 插入时保持链表有序(按 IPv4 地址从小到大排序)。 4. 实现以下接口: - `add_item(...)`: 添加 MAC + IPv4 节点 - `del_item_by_mac(...)`: 根据 MAC 删除节点 - `del_item_by_ip(...)`: 根据 IPv4 删除节点 - `find_ip_by_mac(...)`: 根据 MAC 查找 IPv4 - `find_mac_by_ip(...)`: 根据 IPv4 查找 MAC --- ## 🧱 一、定义结构体 ```c #include <linux/list.h> #include <linux/types.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/in.h> struct mac_ip_entry { u8 mac[6]; // MAC 地址 __be32 ip; // IPv4 地址,使用网络字节序 struct list_head list; // 链表节点 }; ``` --- ## 🧪 二、链表初始化 你可以定义一个全局链表头: ```c static LIST_HEAD(mac_ip_list); // 全局链表头 ``` --- ## 🧩 三、接口实现 ### 1. `add_item(...)`:插入一个 MAC + IPv4 节点,并保持有序 ```c int add_item(u8 *mac, __be32 ip) { struct mac_ip_entry *new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); if (!new_entry) return -ENOMEM; memcpy(new_entry->mac, mac, 6); new_entry->ip = ip; INIT_LIST_HEAD(&new_entry->list); // 插入到链表中并保持有序 struct mac_ip_entry *pos; list_for_each_entry(pos, &mac_ip_list, list) { if (ntohl(new_entry->ip) < ntohl(pos->ip)) { list_add_tail(&new_entry->list, &pos->list); return 0; } } // 如果链表为空或插入到最后 list_add_tail(&new_entry->list, &mac_ip_list); return 0; } ``` --- ### 2. `del_item_by_mac(...)`:根据 MAC 删除节点 ```c int del_item_by_mac(u8 *mac) { struct mac_ip_entry *pos, *tmp; list_for_each_entry_safe(pos, tmp, &mac_ip_list, list) { if (memcmp(pos->mac, mac, 6) == 0) { list_del(&pos->list); kfree(pos); return 0; } } return -ENOENT; // 未找到 } ``` --- ### 3. `del_item_by_ip(...)`:根据 IPv4 删除节点 ```c int del_item_by_ip(__be32 ip) { struct mac_ip_entry *pos, *tmp; list_for_each_entry_safe(pos, tmp, &mac_ip_list, list) { if (pos->ip == ip) { list_del(&pos->list); kfree(pos); return 0; } } return -ENOENT; } ``` --- ### 4. `find_ip_by_mac(...)`:查找 MAC 对应的 IPv4 ```c __be32 find_ip_by_mac(u8 *mac) { struct mac_ip_entry *pos; list_for_each_entry(pos, &mac_ip_list, list) { if (memcmp(pos->mac, mac, 6) == 0) return pos->ip; } return 0; // 0.0.0.0 表示未找到 } ``` --- ### 5. `find_mac_by_ip(...)`:查找 IPv4 对应的 MAC ```c u8 *find_mac_by_ip(__be32 ip) { struct mac_ip_entry *pos; list_for_each_entry(pos, &mac_ip_list, list) { if (pos->ip == ip) return pos->mac; } return NULL; } ``` --- ## 🔍 四、辅助打印函数(调试用) ```c void print_mac_ip_list(void) { struct mac_ip_entry *pos; list_for_each_entry(pos, &mac_ip_list, list) { printk(KERN_INFO "MAC: %pM, IP: %pI4\n", pos->mac, &pos->ip); } } ``` --- ## 🧪 、完整模块示例(可选) 如果你是写一个内核模块,可以加上 `module_init` 和 `module_exit` 来测试: ```c static int __init mac_ip_init(void) { u8 mac1[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; u8 mac2[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66}; __be32 ip1 = htonl(0xc0a80101); // 192.168.1.1 __be32 ip2 = htonl(0xc0a80102); // 192.168.1.2 add_item(mac1, ip1); add_item(mac2, ip2); print_mac_ip_list(); del_item_by_mac(mac1); print_mac_ip_list(); return 0; } static void __exit mac_ip_exit(void) { // 清理所有节点 struct mac_ip_entry *pos, *tmp; list_for_each_entry_safe(pos, tmp, &mac_ip_list, list) { list_del(&pos->list); kfree(pos); } } module_init(mac_ip_init); module_exit(mac_ip_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("MAC-IP List Module"); ``` --- ## ✅ 总结:你已完成的内容 | 功能 | 是否完成 | |------|----------| | 使用 `struct list_head` 实现链表 | ✅ | | 插入节点并保持有序 | ✅ | | 添加 MAC+IPv4 节点 | ✅ | | 删除节点(按 MAC) | ✅ | | 删除节点(按 IP) | ✅ | | 查找 IP(按 MAC) | ✅ | | 查找 MAC(按 IP) | ✅ | | 模块测试(可选) | ✅ | --- ## ❓相关问题这个文件的拓扑结构是什么
09-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值