美文网首页C语言基础学习
《C语言36—不同数据类型的strcpy》

《C语言36—不同数据类型的strcpy》

作者: 竹予青青 | 来源:发表于2019-04-09 20:20 被阅读97次

2019年4月9日星期二 中雨转小雨


在微信公众号里看见一个题目,自己来试了一下,于是将其做一个记录。
公众号的名称是“C语言与程序设计”,原文链接是:一道C语言面试题,真的不简单!


原程序是:

#include <stdio.h>
#include <string.h>

int main(void)
{
    char s[] = "abcdefghijklmnopqrstuvwxyz";
    char d[] = "123";
    strcpy(d, s);
    printf("%s %s", s, d);

    return 0;
}

我在vs2017里面将strcpy格式改成strcpy_s后变成:

#include <stdio.h>
#include <string.h>

int main(void)
{
    char s[] = "abcdefghijklmnopqrstuvwxyz";
    char d[] = "123";
    strcpy_s(d,100, s);
    printf("%s %s", s, d);

    return 0;
}

运行程序之后出现如下情况:


运行结果与报错信息

从显示的结果看,运行结果是:

mnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz

但是在运行结果出来后却报错了:

Run-Time Check Failure #2 - Stack around the variable 's' was corrupted.

s是错误的?


(我和这篇文章的作者的运行结果有所不同,据说是因为具体分配内存有可能不一样。)
以下是作者的说法:
请看题:

原题目

题目描述很简单,让你分析它的输出。

  • 小伙伴A说,这不就是把s复制到d嘛,所以输出自然是s不变,d变为s了啊。
  • 小伙伴B说,很明显复制到d时越界了啊,程序会报错然后停止运行啊。
  • 小伙伴C说,应该没有表面上越界这么简单,我得好好思考一下,肯定会有陷阱,等我调试一下再给出答案。

以上是3种说法,我们先不评论,直接给出程序运行结果:


运行结果

咦?很奇怪,输出d是正确的,s发生了截断!要说越界也应该是d错啊,这是什么情况?大家不要着急,我们一步步来分析调试找原因。

首先我们先来回顾一下strcpy函数的原理,把一个字符串复制到一个字符串上并在末尾追加空字符,但没有越界检验,安全性堪忧。但此题看运行结果是复制成功了,不应该是越界吗?

那再往下就不能靠分析了,得调试程序找错了,说白了现在问题就在越界这里,似乎得用我们的利器printf查看字符串存储的内存地址了,上图:

调试 调试结果

看到内存地址我们好像明白了点什么,d的起始地址为20,s起始地址为30,也就是说系统并不是跟我们想像的那样给数组d只分配了4字节的内存,而是分配了16字节(内存地址为16进制)!

到这里,基本就全明白了,应该是把s复制到d中时,26个字母占用26字节确实越界了,占用了s本身的一些存储空间,d原来的16字节空间存了到p的16个字母,从q开始剩下的10个字母把原先s中的前十一个字母覆盖了(因为strcpy还追加了空字符),当最后打印%s 时,直到空字符打印才停止,因此d打印正确,s只打印了从q开始的10个字母,我们把s改为10个字母来验证一下我们的推测:

结果正确!当然,具体给d分配多少空间可能取决于编译器和系统的具体实现,但可以肯定的是只要不够27字节,s肯定会发生截断,而且在d仅为字符串123的前提下,d的空间99%不会达到27字节,也就是s很大几率要截断。

此题还有一点没讲,如果把s和d的那两行代码交换一下位置会发生什么呢?这个就留给大家吧,提醒一下没那么简单哦!


以下是我的调试及后续调整的运行过程与结果:
调试的结果是:

004FFC54 004FFC48
mnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz

在结果出来后,也还是报错了。

后面的过程我还没怎么看懂,先搁置吧。


Weif
2019年4月9日

相关文章

  • 《C语言36—不同数据类型的strcpy》

    2019年4月9日星期二 中雨转小雨 在微信公众号里看见一个题目,自己来试了一下,于是将其做一个记录。公众号的名...

  • Strcpy & Strncpy

    Strcpy strcpy是一种C语言的标准库函数,strcpy把从src地址开始且含有'\0'结束符的字符串复制...

  • OC和C中的数据类型

    数据类型对比 C语言数据类型C语言数据类型 OC数据类型

  • c/c++补完计划(二): c字符串复制

    前言 c字符串复制的实现, 基本参考strcpy源码. 正文 不同于strcpy的点在于, 传入只有src串, 没...

  • C语言基础教程之数据类型

    C语言中的类型可分为以下四类,C语言基础教程之数据类型 c中的数据类型是指用于声明不同类型的变量或函数的扩展系统。...

  • 【OC梳理】基本数据类型和基本运算

    Objective-C作为以C语言为基础的语言,其基本数据类型与C语言类似。 1.基本数据类型 基本数据类型可以参...

  • c++与c-strcpy()与memset()

    来源:菜鸟教程 strcpy() 1.C 标准库 - 2.描述C 库函数 char *strcpy(char *...

  • 【初识C语言】C语言基本数据类型

    C语言基本数据类型简介 1.概述 C 语言包含的数据类型如下图所示: C语言中的基本数据类型有整形、字符型、浮点型...

  • Chapter02-整数的表示

    1.整型数据类型 C语言支持多种整型数据类型,例如char、short、int等,64位机器上,不同的数据类型所表...

  • Go语言指针

    只讲述和C语言地址的不同 格式:var 指针名称 *数据类型var 指针名称 *数据类型 = 地址 指向数组的指针...

网友评论

    本文标题:《C语言36—不同数据类型的strcpy》

    本文链接:https://www.haomeiwen.com/subject/qwgiiqtx.html