C语言中字符串函数的思考

 2024-02-17 04:02:11  阅读 0

2. 字符串构造函数

2.1 不安全

如上面的例子,我在修改copy函数的同时,还想到了另一个我常用的字符串构造函数。 显然,这个函数没有定义目标地址空间的大小,是不安全的。 以下代码将导致崩溃。 :

空白()

整数我;

字符 szBuf[128];

for(i=0;[127]='\0';

字符[256];

for(i=0;[255]='\0';

(szBuf,);

("%s\n",szBuf);

2.2 仍然不安全

查看库函数手册,找到这样的函数。 其函数原型如下:

int ( char *, count, const char * [, ] ... );

此功能允许您定义目标地址大小。 然而,由于我研究复制函数的经验,我怀疑它也有同样的问题。 因此,我写了这段代码来测试:

空白()

整数我;

字符 szBuf[128];

for(i=0;[127]='\0';

字符[256];

for(i=0;[255]='\0';

(szBuf,8,);

("%s\n",szBuf);

果然,程序输出如下:

c++字符串列表_c语言字符串例子_c语言字符串 列表

########************************************************ ******************************************

同样的错误,不是以“\0”结尾,我必须找到另一种方法。

除此之外,还发现了另一个缺点。 此时函数返回-1,不再返回打印字符数。 那么,如果我们使用下面的代码,就会导致逻辑错误,甚至可能崩溃:

字符 szBuf[256];

整数=0;

while(1) //这代表循环构造

+=(szBuf+,256-,"... ..."); //多个字符串构造成一个字符串

请注意,代码使用返回值来确定下一个起点,这很常见。 但返回-1时,可能会写入到*(szBuf-1)位置,这是典型的内存写越界。

2.3 安全字符串构造函数

经过深思熟虑,我构造了以下函数:

int (char* szBuf,int ,char *, ...)

整数=0;

;

(,);

+=(szBuf+,

-,,);

();

*(szBuf+-1)='\0';

(szBuf);

请注意,我在这里使用了可变参数函数设计,以方便与将这个函数代入上面的示例后,一切正常。

总结:C语言字符串库函数可能是为了提高性能的目的。 当条件不够时,往往直接返回,忘记用“\0”结束字符串。 这会导致下次读取字符串时数据边界不可控。 格式化打印函数的返回值设计不合理,并不总是正整数,可能会造成逻辑危险。 所以我建议大家有兴趣的可以参考我提供的两个函数。

另外,以上只是我个人的测试工作。 限于我自己的水平。 一定有一些事情我没有考虑到。 欢迎大家讨论。 如果需要以上源码请联系我。

C语言并不是一种很方便的语言,它的字符串就是一个例子。 根据C语言的定义,“字符串是一段包含ASCII字符、以“\0”结尾的内存空间,总共可以存储n-1个字符。 根据这个描述,字符串处理确实很麻烦,而且很容易出错。

为了方便用户,C语言标准库为用户提供了一些字符串函数,如字符串复制、构造、清除等功能,在一定程度上方便了用户使用。 然而,我无意中发现这些功能仍然存在一些隐患。

事情很简单。 我注意到我编写的一些程序总是出现内存读写错误。 不过,仔细检查了我所有的数据以及相关的处理函数后,并没有发现任何错误。 于是我把怀疑的目光投向了我常用的一些字符串处理函数,比如等等,仔细跟踪了几下,发现内存错误就是从这里来的。 于是,我开始研究如何安全使用字符串这个话题。

1.字符串复制功能

1.1 不安全

首先,我写了一个这样的函数:

空白()

整数我;

字符 szBuf[128];

for(i=0;[127]='\0'; //构造一个全是*的字符串

字符[256];

for(i=0;[255]='\0'; //构造一个全是#的字符串

(szBuf,);

("%s\n",szBuf);

很简单,复制一个字符串到另一个空间,但是不幸的是,源字符串比目标地址长,所以程序就惨死了。

1.2 仍然不安全

通过上面的例子,我发现复制的时候需要额外输入一个参数来表示目的地址有多长。 查看C语言库函数说明,有一个可以实现这一目的。 该函数的原型如下:

char *( char *, const char *, count );

好了,现在我们的问题解决了,我写了如下代码:

空白()

整数我;

字符 szBuf[128];

for(i=0;[127]='\0';

字符[256];

for(i=0;[255]='\0';

(szBuf,,128);

c语言字符串 列表_c++字符串列表_c语言字符串例子

("%s\n",szBuf);

看起来一切都很好,但是当我输出结果时,我发现了一个问题。 字符串后面有时会跟着几个奇怪的字符,好像不是以“\0”结尾,所以我把上面的复制语句改为“(szBuf,,8);”,只复制了8个字符,出现问题,程序输出如下:

########************************************************ **************************

果然,当请求的目标地址空间小于源字符串空间时,将不再使用“\0”来终止字符串。 隐患巨大。

1.3 安全字符串复制功能

我仔细想了想,我觉得我需要一个字符串复制函数,如下:

1. 允许使用整数来定义目标地址空间大小。

2. 当目标地址空间nD小于源字符串长度nS时,只需要复制nD个字节。

3. 无论如何,目标地址空间都应该以“\0”结尾,以保持合法的字符串标识。 因此,生成的字符串的最大长度为 nD-1。

所以,我写了一个这样的字符串复制函数:

无效(字符*pD,字符*pS,int)

(pD,pS,);

*(pD+-1)='\0';

这很容易。 将这个复制函数代入上面的例子,只输出7个“#”,结果是正确的。

1.4 关于内存读取错误的思考

我原本以为可以就此打住,但没过多久,我就发现了一个奇怪的现象。 该函数在VC的Debug模式下出现错误,但在该模式下一切正常。

我想了很久,终于有一天我实在忍不住了,决定解决这个问题。 我用自己的复制循环替换了上面的内容,并一步跟踪了它。 我想看看到底是怎么回事?

原因找到了。 我想复制一个256字节的字符串,但是复制到第33个字节时出现错误。 检查程序后发现我的源字符串空间只有32 Bytes。 原来上面的代码只是阻止了内存写越界,但是并没有对读越界进行检查。 在VC的Debug模式下,内存读取越界也是非法错误,所以报错。

知道了原因,解决办法就很简单了。 我将上面的复制函数更改为以下形状:

无效(字符*pD,字符*pS,int)

int nLen=(pS)+1;

if(nLen>) nLen=;

(pD,pS,nLen);

*(pD+nLen-1)='\0';

一切都好。

标签: 字符 函数 拷贝

如本站内容信息有侵犯到您的权益请联系我们删除,谢谢!!


Copyright © 2020 All Rights Reserved 京ICP5741267-1号 统计代码