memcpy_s这类安全函数使用介绍(来自安全 C 库: Safe C Library )

本文主要对带有 _s 的这类 安全 函数(如 memcpy_s)进行简单介绍,以及如何在自己的 Linux 开发环境中使用这些函数。

1. 引入这类安全函数

  最近在写程序时,涉及内存拷贝的问题,比如我这里有三个字符类型数组 a、b、c,可以理解为三个缓冲区,其中 a 和 b 中的 内容需要根据 c 中的内容进行构建,a 取其中的前半段,b 取其中的后半段,需要取的长度已知。
  显然,这里可以使用内存拷贝函数 memcpy。你知道从 c 缓冲区的那个地方开始,到哪里结束应该给 a 缓冲区和 b 缓冲区,使用 memcpy 进行定长拷贝,这种做法很便捷。但是,我却被同事告知这种做法不是很安全,应当使用 memcpy_s 函数来进行定长(内存)拷贝。那我心里就产生了一个疑问:为什么这些函数更加安全,标准库却没有引入呢?
  随即,我发现不仅仅有 memcpy_s,还有很多类似的函数,如:strncpy_s、memmove_s、memset_s、snprintf_s、strcpy_s 等等,有这么一类函数的存在,他们被称之为 C 的安全库函数,但是却不在标准库中,标准库中的这些函数,都是不带有 _s 的。

2. 安全类函数介绍
2.1 这类函数的背景

  这类所谓的安全函数最初是由微软( Microsoft )为 Windows 平台实现的,其官方名字为 Safe C Library,见其官网 ,这里有这些函数的详细介绍,以及函数实现的文件依赖图( Include dependency graph )。但是有很多组织机构是反对将这些纳入 C 标准库中的,尽管最终微软说服 C 标准委员会( C standard committee) 将这些函数加入附录 K 中,但是这些函数仍然不是标准库的一部分。这些安全函数从 C11 标准才开始支持,但似乎也仅限于 MSVC (微软的 VC 运行库)。以上,大概就能够解释为什么官方手册中给的示例程序在自己的 Linux 开发机中无法编译、运行,即便引入了 srting.h 头函数,即便你在程序中定义了文档中所说必须的宏,也还是会显示找不到 memcpy_s 函数的定义。如果你真的去查找了一遍,就会发现,string.h 文件中根本没有对应的这些函数。
  至此,你可以理解为,这一类所谓更安全的函数,是微软的 VC 运行库中的函数,对于其他平台,默认并不支持,当今强制推广这些安全函数的只有 Windows 平台。(啊这,微软写的,自己不得给自己捧场。)

2.2 源码对比分析

  这里源码对比分析仅限于 memcpy 与 memcpy_s。
  搞清楚了它的背景,来谈一下相比于标准库的这些函数,这些函数有什么改进的地方。
  我们来拿 memcpy 函数与 memcpy_s 函数举例。先来看看 memcpy 函数的源码实现:

/* libgcc/memcpy.c */
#include <stddef.h>
void *
memcpy (void *dest, const void *src, size_t len)
{
   
  char *d = dest;
  const char *s = src;
  while (len--)
    *d++ = *s++;
  return dest;
}

  这里的源码来自 libgcc/memcpy.c, 不同地方的源码实现可能稍有差异(目前我见过三个版本,大同小异吧),总体而言,memcpy 函数实现较为简单,并不会对指针是否合法、缓冲区长度是否满足拷贝的需要进行检查。再来看一下 memcpy_s 函数。memcpy_s 函数的实现如下:

#ifdef FOR_DOXYGEN
#include "safe_mem_lib.h"
#else
#include "safeclib_private.h"
#include "mem/mem_primitives_lib.h"
#
~/power/bin # gdb netmgr GNU gdb (GDB) 8.1 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "arm-unknown-linux-gnueabihf". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from netmgr...done. (gdb) r Starting program: /root/power/bin/netmgr [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1". Signal is about to be caught. Preparing to handle it... route: SIOCDELRT: No such process route: SIOCDELRT: No such process killall: udhcpc: no process killed killall: udhcpc: no process killed [New Thread 0xb583d400 (LWP 424)] [New Thread 0xb4eff400 (LWP 430)] [New Thread 0xb46fe400 (LWP 431)] Thread 1 "netmgr" received signal SIGSEGV, Segmentation fault. 0xb6a97d24 in memcpy () from /lib/libc.so.6 (gdb) bt #0 0xb6a97d24 in memcpy () from /lib/libc.so.6 #1 0xb6b82028 in zte_memcpy_s () from /root/power/lib/libzte_slibc.so #2 0x0002ce9c in __frame_dummy_init_array_entry () Backtrace stopped: previous frame identical to this frame (corrupt stack?) 如何定位到段错误的代码行数
最新发布
04-02
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草台班主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值