免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 10116 | 回复: 16
打印 上一主题 下一主题

[C] 请问strcpy为何导致"段错误",很短的小程序 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-02-15 22:10 |只看该作者 |倒序浏览
10可用积分
如题,下面这个小程序运行结果是段错误
#include<stdio.h>
#include<string.h>
#include<ctype.h>
void f(char* s){
    int len=strlen(s);
    char buf[len+1];
    strcpy(buf,s);
    printf("s=%s,buf=%s\n",s,buf);
    strcpy(s,buf);
    printf("after strncpy\n");
}
int main(void){
        f("abc");
        return 0;
}
./a.out
s=abc,buf=abc
段错误
如果我把main函数的内容改为
        char b[]="abc";
        f(b);
运行就没有问题。

请教dx为什么上面那个用法运行到第2个strcpy的时候就会产生段错误呢? 都是静态的字符串传入,一个显示声明了,一个直接传入的。

10分感谢!

[ 本帖最后由 jeanlove 于 2009-2-16 10:11 编辑 ]

最佳答案

查看完整内容

哦。“abc”是存在只读属性数据区,不能做strcpy的目的地数组内存分配在栈上,可作修改,所以数组名可以做strcpy的第一个参数。[ 本帖最后由 bert1984 于 2009-2-15 22:22 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-02-15 22:10 |只看该作者
哦。“abc”是存在只读属性数据区,不能做strcpy的目的地
数组内存分配在栈上,可作修改,所以数组名可以做strcpy的第一个参数。

[ 本帖最后由 bert1984 于 2009-2-15 22:22 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-02-15 22:18 |只看该作者
int len=strlen(s);
有错误。 len=4
而不是s字符串长度

论坛徽章:
0
4 [报告]
发表于 2009-02-15 22:36 |只看该作者
"abc"表示的是字符串常量
char b[]="abc";表示char数组b,里面存放的是'a','b','c','/0',表示字符串,和"abc"并不是同一内存地址

int len=strlen(s);
    char buf[len+1];

这句有问题吧,我编译都通不过,数组定义下标必须是常量吧

char *buf = new char[len+1]; 这样写

[ 本帖最后由 nickiii 于 2009-2-15 22:41 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2009-02-15 22:41 |只看该作者
f("abc");

中的abc是个常量,你不能往里面copy东西,所以断错误。

论坛徽章:
0
6 [报告]
发表于 2009-02-15 22:41 |只看该作者
应该是第二个strcpy出现段错误的吧, 你试图改变静态数据区的数据s, 所以出错了.

论坛徽章:
0
7 [报告]
发表于 2009-02-15 22:45 |只看该作者
f("abc");
将常量区指针(指向"abc")做为参数传给f

char b[]="abc";
f(b);
分配四个字母,初始化为abc\0
并将地址赋值给b
调用函数f,将b做为参数传给函数f

常量区的内容只读不可写

论坛徽章:
0
8 [报告]
发表于 2009-02-15 22:48 |只看该作者
void f(char* s)
{
    int len=strlen(s);
    char buf[len+1];
    strcpy(buf,s);
    printf("s=%s,buf=%s\n",s,buf);
    strcpy(s,buf);   //问题出在这里
    printf("after strncpy\n");
}

main()函数中你把字符串常量“abc”的首地址传给s
s指向的就是只读区域
你执行strcpy(s, buf)要将buf数组里的内容拷贝到s指向的空间,而现在s指向的空间是只读的,于是出现段错误

char b[]="abc";
你把字符串"abc"定义在字符数组里,“abc”是存放在堆栈中的,当你把b的值传给函数f()里的s时候,s指向堆栈空间,这个区域是可以读写的,所以不会出现段错误了

[ 本帖最后由 zhuhefang2006 于 2009-2-15 22:53 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2009-02-16 07:42 |只看该作者
我觉得很多人都不理解一个“无定义”的概念。就像 0/0,结果是多少?在实数范围里这样的运算就是没有定义,除非你去定义一下,结果你说了算。
其实按照 K&R 上的说法,试图修改 string literal 可能导致的结果:无定义。
谁也不知道会发生什么,因为标准里没有定义。但只要你知道你用的是什么样的编译环境,你就知道会发生什么,因为你落实到了具体的实现。比如,GCC Linux/i386 把 string literals 设定为只读,你试图修改它,MMU 就让 CPU 向操作系统发出警告,操作系统又向进程发出 SIGSEGV 信号,这个信号的默认行为是终止进程。

论坛徽章:
0
10 [报告]
发表于 2009-02-16 09:15 |只看该作者
strcpy(buf,s);如果s是常量的话,这个行为在C的标准上没有定义,看编译器自身的实现了,如果s只读,那么就有可能出现段错误
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP