在编写程序来反转字符串后,我无法理解为什么在尝试反转字符串时遇到seg错误。我在下面列出了我的程序。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse(char *);
int main() {
char *str = calloc(1,'\0');
strcpy(str,"mystring0123456789");
reverse(str);
printf("Reverse String is: %s\n",str);
return 0;
}
void reverse(char *string) {
char ch, *start, *end;
int c=0;
int length = strlen(string);
start = string;
end = string;
while (c < length-1){
end++;
c++;
}
c=0;
while(c < length/2){
ch = *end;
*end = *start;
*start = ch;
start++;
end--;
c++;
}
}
第一个问题:
即使我只为char指针分配了1个字节的内存
str(calloc(1,'\0')
),我将一个18字节的字符串mystring0123456789
复制到其中,它没有抛出任何错误,程序运行正常,没有任何SEGFAULT。
为什么我的程序没有抛出错误?理想情况下它应该抛出一些错误,因为它没有任何内存来存储那个大字符串。有人可以对此有所了解吗?
该程序运行良好,并为我提供输出Reverse String is: 9876543210gnirtsym
。
第二个问题:
如果替换声明
strcpy(str,"mystring0123456789");
与
str="mystring0123456789\0";
即使我为str(malloc(100)
)分配了足够的内存,该程序也会出现分段错误。
为什么程序会抛出分段错误?
答案 0 :(得分:5)
即使我只为char指针str(calloc(1,'\ 0'))分配了1个字节的内存,并且我将18字节的字符串“mystring0123456789”复制到其中,并且它没有抛出任何内容错误,程序工作正常,没有任何SEGFAULT。
你的代码有一个错误 - 当然它不会做你期望的。修复错误,神秘感将会消失。
如果更换声明
的strcpy(STR “mystring0123456789”);
与
STR = “mystring0123456789 \ 0”;
即使我为str(malloc(100))分配了足够的内存,程序也会给出分段错误。
因为完成此操作后,str
指向常量。这会丢弃先前的str
值,这是一个指向你分配的内存的指针,并用指向该常量的指针替换它。
你不能修改一个常数,这就是使它成为常数的原因。 strcpy
函数将常量复制变量,然后您可以修改该变量。
想象一下,如果你能做到这一点:
int * h =&amp; 2;
现在,如果您执行了*h = 1;
,那么您将尝试在代码中更改常量 2,这当然是您无法做到的。
这实际上就是你在str="mystring0123456789\0";
所做的。它使str
指向源代码中的常量,当然,您无法修改。
答案 1 :(得分:2)
答案 2 :(得分:0)
你的程序没有抛出错误,因为,即使你做错了什么,也没有抓到你(更多信息如下)。你写的数据是你不应该的,但你有“幸运”,并且没有做任何事情。
strcpy(str,"mystring0123456789");
将数据复制到str
分的位置。碰巧的是,在那个地方,你可以在不引起陷阱的情况下编写数据(这次)。相比之下,str="mystring0123456789\0";
将str
更改为指向新位置。它指向的地方是"mystring0123456789\0"
存储的地方。那个地方很可能是只读内存,因此,当你试图在reverse
程序中写入它时,你会得到一个陷阱。
更多关于1:
当calloc
分配内存时,它只会安排一些你允许使用的空间。 物理,还有其他内存。您可以写入其他内存,但不应该。这正是现实世界中的工作方式:如果您租用酒店房间,允许使用该酒店房间,但即使他们碰巧使用其他房间也是错误的开放。
有时当你侵入你不应该去的地方时,在现实世界或程序中,没有人会看到,你就会侥幸逃脱。有时你会被抓住。你不被抓住的事实并不意味着它没事。
关于calloc
的另一个注意事项:您要求它为一个零大小的事物分配空间(源代码'\0'
的计算结果为零)。所以你要求零字节。各种标准(例如C和Open Unix)可能会对此有不同的看法,因此,当您要求零字节时,calloc
会给您一个字节。但是,它肯定不会为您提供与strcpy
一样多的字节数。
答案 3 :(得分:0)
听起来你正在编写的C程序来自动态语言,或者至少是一种自动字符串处理的语言。由于缺乏更正式的定义,我发现C是一种非常接近机器架构的语言。也就是说,你做了很多编程决策。很多程序问题都是代码导致未定义行为的结果。你有一个带有strcpy的段错误,因为你将内存复制到受保护的位置;行为未定义。然而,指定固定字符串“mystring0123456789 \ 0”只是将指针指定给str。
在C中实现时,您决定是要在编译时还是在运行时定义存储区域,还是决定从堆中分配存储(malloc / calloc)。在任何一种情况下,您都必须编写内务处理例程,以确保不超过您定义的存储空间。
将字符串分配给指针只是将字符串的地址分配给内存;它不会复制字符串,并且引号“test-string”中的固定字符串是只读的,您无法修改它。你的程序可能已经完成了这项任务,即使它不被认为是好的C编码实践。
以这种方式处理存储分配是有好处的,这就是C是一种流行语言的原因。
答案 4 :(得分:0)