内存分区、字符串逆置函数读写发生访问冲入的原因

题目:将一个字符串逆置输出

我下写的代码如下:

void reserve_string(char *string)

{

       char tmp;//变量tmp用来做交换

       char *first_str = string;//字符串的首指针

       char *last_str = string;//尾指针

       while(*last_str != '\0')//让尾指针指向最后

       {

              last_str++;

       }

       last_str--;//此时尾指针指向'\0',所以自减一,指向最后一位

       while(first_str < last_str)//交换

       {

              tmp = *first_str;

              *first_str = *last_str;//访问冲突 0x00161430 处有未经处理的异常(在 c和指针1.1次作业 指针.exe 中):

              *last_str = tmp;//0xC0000005: 写入位置 0x0016585C 时发生访问冲突。

              first_str++;

              last_str--;

       }

       printf("%s",string);

}

 

int main()

{

       //char string1[] = "abcdefghijklmnopqrstuvwxyz";//ok,可以运行处结果

       //reserve_string(string1);

       char *string2 = "abc";

       reserve_string(string2);//错误,程序崩溃

       return 0;

}

程序崩溃,调试时出现“发生访问冲突”的字样:

观察崩溃时代码位置:

*first_str = *last_str;在指针解引用赋值时,不能写入。

解决:

在上一篇博客中写到内存的四个分区,如下图:

这里要更改:代码段的区域为常量区。(上一篇博客中我所忽略的,导致了这个函数bug)

 

在c中分为这几个存储区:堆、栈、全局区(静态区)、常量区 
(1).栈 - 由编译器自动分配释放。 栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。 
(2).堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统回收。 堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减) 
(3).全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束释放 
(4).另外还有一个专门放常量的地方,叫做常量区,是存在于代码段的。-指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。代码段是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。

所以问题的根源找到了:字符串常量(*string = “abc”)是只读的常量,不可以修改,所以在进行赋值时,报错:写入访问冲突。

解决方法:用数组来做:

       char string1[] = "abcdefghijklmnopqrstuvwxyz";//ok,可以运行处结果

       reserve_string(string1);

数组中的元素是可以修改的,也就是说数组元素还是变量。

那么访问冲突有几种情况?原因总结:

  1. 使用未初始化的指针
  2. 使用已经删除的指针
  3. 数据越界
  4. 空指针
  5. 还有今天遇到的,给常量赋值,因为常量时只读的

猜你喜欢

转载自blog.csdn.net/zDavid_2018/article/details/82686408