今天使用VS2019编写程序,采用动态内存分配,但是在释放内存时出现问题。
程序使用了动态内存分配,因此需要程序员手动释放空间。
然而释放过程出现问题。 设置断点调试后,发现报错语句在这三行
原始代码如下,该程序的作用是从串s中删除所有和串t相同的子串。
程序本身效率高低不在本篇博客讨论范围,详情自行百度。
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int* brute_force(const string& s,const string& t)
{
int* pos = new int[ s.length() / t.length() ];
int i, j, n=1, s_len = s.length(), t_len = t.length();
bool flag;
pos[0] = 0;
for (i = 0; i < s_len; ++i) {
flag = true;
for ( j = 0; j < t_len; ++j)
{
if (s[i+j]!=t[j])
{
flag = false;
break;
}
}
if (flag==true)
{
++pos[0];
pos[n] = i;
++n;
}
}
return pos;
}
void problem413_Brute_Force()
{
string s, t;
cout << "input s :" << endl;
cin >> s;
cout << "input t :" << endl;
cin >> t;
int* pos = brute_force(s,t);
char* sub_s = new char[s.length() - pos[0] * t.length() ];
int j=0, s_len = s.length(), t_len = t.length();
int* at_subs = new int[s_len];
for (int i = 0; i < s_len; ++i) {
at_subs[i] = 1;
}
for (int i = 1; i <= pos[0]; ++i)
{
for (j = pos[i]; j < pos[i] + t_len; ++j) {
at_subs[j] = 0;
}
}
int n = 0;
for (int i = 0; i < s_len; ++i)
{
if (at_subs[i] == 1) sub_s[n++] = s[i];
}
sub_s[n] = '\0';
cout << sub_s << endl;
delete sub_s;
delete pos;
delete at_subs;
return;
}
int main()
{
problem413_Brute_Force();
}
本博客主要解决上述堆内存报错时的分析。
首先使用暴力算法求出s中每一个包含t的位置,之后返回包含信息的数组pos。
pos[0]代表总共重复的次数,其余的pos[i]代表第i次重复时,s中出现的t串在s中的位置。
比如,s=“acdacdacdb” t=“acd”
那么,pos[0]=3 , pos[1]=0 , pos[2]=3 , pos[3]=4
其中,pos为动态申请所得。
同样的,subs,at_subs均由动态内存分配得来。
分析后发现,这一句会分配的空间不足以支持后面的操作,即后面出现的越界访问的情况。因为修改了申请的内存以外的内存,从而导致释放指针指向的堆内存出现错误。
也就是说,pos[0]=3 , pos[1]=0 , pos[2]=3 , pos[3]=4 这些信息需要4个int的空间存储,但是只分配了 int(10/3) = 3个空间,因此会出现内存访问越界的情况。
同时,这一语句也可能因为s串和t串没有重复的,
,而在后面这句中报错,(越界访问,因为 n 的值已经超过了sub_s的分配得到的最大长度)
修改的方法,将上述两句改为如下即可,即适当多分配一些空间,以免内存访问越界: