作者wtchen (没有存在感的人)
看板C_and_CPP
标题十三诫增修--04:你不可以试图用 char* 去更改一个"字串常数"
时间Sat May 14 16:45:03 2016
04.
你不可以试图用 char* 去更改一个"字串常数"
试图去更改字串常数(string literal)的结果会是undefined behavior。
错误例子:
char* pc = "john"; /* pc 现在指着一个字串常数 */
*pc = 'J'; /* undefined behaviour,结果无法预测*/
pc = "jane"; /* 合法,pc指到在别的位址的另一个字串常数*/
/* 但是"john"这个字串还是存在原来的地方不会消失*/
因为char* pc = "john"这个动作会新增一个内含元素为"john\0"的static char[5],
然後pc会指向这个static char的位址(通常是唯读)。
若是试图存取这个static char[],Standard并没有定义结果为何。
pc = "jane" 这个动作会把 pc 指到另一个没在用的位址然後新增一个
内含元素为"jane\0"的static char[5]。
可是之前那个字串 "john\n" 还是留在原地没有消失。
通常编译器的作法是把字串常数放在一块read only(.rdata)的区域内,
此区域大小是有限的,所以如果你重复把pc指给不同的字串常数,
是有可能会出问题的。
正确例子:
char pc[] = "john"; /* pc 现在是个合法的阵列,里面住着字串 john */
/* 也就是 pc[0]='j', pc[1]='o', pc[2]='h',
pc[3]='n', pc[4]='\0' */
*pc = 'J';
pc[2] = 'H';
说明:字串常数的内容应该要是"唯读"的。您有使用权,但是没有更改的权利。
若您希望使用可以更改的字串,那您应该将其放在合法空间
错误例子:
char *s1 = "Hello, ";
char *s2 = "world!";
/* strcat() 不会另行配置空间,只会将资料附加到 s1 所指唯读字串的後面,
造成写入到程式无权碰触的记忆体空间 */
strcat(s1, s2);
正确例子(2):
/* s1 宣告成阵列,并保留足够空间存放後续要附加的内容 */
char s1[20] = "Hello, ";
char *s2 = "world!";
/* 因为 strcat() 的返回值等於第一个参数值,所以 s3 就不需要了 */
strcat(s1, s2);
C++对於字串常数的严格定义为const char* 或 const char[]。
但是由於要相容C,char* 也是允许的写法(不建议就是)。
不过,在C++试图更改字串常数(要先const_cast)一样是undefined behavior。
const char* pc = "Hello";
char* p = const_cast<char*>(pc);
p[0] = 'M'; // undefined behaviour
备注:
由於不加const容易造成混淆,
建议不管是C还是C++一律用 const char* 定义字串常数。
补充资料:
http://en.cppreference.com/w/c/language/string_literal
http://en.cppreference.com/w/cpp/language/string_literal
字串函数相关:
#1IOXeMHX
undefined behavior : z -> 3 -> 3 -> 23
--
个人网页:
http://gnitnaw.github.io/
以後在C_and_CPP或LinuxDev发表的文章都会放一份在这边。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 86.209.153.222
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1463215507.A.037.html
※ 编辑: wtchen (86.209.153.222), 05/14/2016 18:00:45
请问一下,若是我不断修改字串函数,像这样:
char *a = "aaaa";
a = "bbbb";
a = "cccc";
....
连续这样很多次的话会不会使得read only区被唯读字串弄爆?
2F:推 Rollnmeow: 有错字 第一个undefined behavior打成了behavoir 05/14 22:34
已修正,谢谢
3F:→ Caesar08: 需要补充undefined behavior是甚麽意思吗? 05/14 22:46
这个FAQ有,我可以加进补充资料。
※ 编辑: wtchen (86.209.153.222), 05/14/2016 23:28:15
※ 编辑: wtchen (86.209.153.222), 05/14/2016 23:32:40
4F:推 EdisonX: 那就得看 .rdata 有多大了, 不过避开弄爆的方法很多 , 但 05/14 23:35
5F:→ EdisonX: 用这特性也可以做一些奇淫怪技。 05/14 23:35
6F:→ wtchen: 可以教一下这邪恶的技巧吗? 05/14 23:40
8F:→ wtchen: 居然还有这招.... 05/14 23:48
根据EdisonX提供的资料改了一下...
※ 编辑: wtchen (86.209.153.222), 05/14/2016 23:58:04