为啥使用动态 ptr 数组检测到分段错误或双重释放?
Posted
技术标签:
【中文标题】为啥使用动态 ptr 数组检测到分段错误或双重释放?【英文标题】:Why am I getting segmentation fault or double free detected with dynamic ptr arrays?为什么使用动态 ptr 数组检测到分段错误或双重释放? 【发布时间】:2021-12-20 11:41:09 【问题描述】:更新:退休的忍者如果你读过这篇文章,非常感谢!摆脱第二个数组的“Todo”修复了所有问题!我已经尝试解决这个问题 8 小时了,哈哈,我真的无法感谢你!
所以我正在制作一个创建 ToDo 列表的程序,但由于我的第一个数组太小而不断收到分段错误,但在代码中我将其删除并使其变大了。
此外,如果我只是将数组设置为更大的数字来临时修复它,我开始在 tcache 2 错误中检测到双重释放。
任何解决方案或建议将不胜感激! 注意:我更喜欢使用向量,但是对于这个赋值,需要一个动态数组。
这是我的代码:
#include <iostream>
#include <sstream>
#include <limits>
#include <ctime>
#include <cstring>
using namespace std;
class Date
public:
Date()
time_t currentdate = time(0);
tm* date = localtime(¤tdate);
cout << "Today's date: " << 1 + date->tm_mon << "/" << date->tm_mday << "/" << 1900 + date->tm_year << endl << endl; // For some reason my system month was only 10 so I had to add 1
;
class Todo
public:
string todoItem, addDate;
int itemID;
void setData(string input, int arraysize)
input.erase(0,1);
todoItem=input;
itemID=arraysize;
stringstream buffer;
time_t currentdate = time(0);
tm* date = localtime(¤tdate);
buffer << "Date added: " << 1 + date->tm_mon << "/" << date->tm_mday << "/" << 1900 + date->tm_year << endl << endl;
addDate = buffer.str();
void getData()
cout <<"GetData:\n";
cout << itemID << "/" << todoItem << "/" << addDate << endl;
;
void ProgramGreeting();
char MenuChoice(string todoItem);
int main()
ProgramGreeting();
bool menuloop=true;
bool firstrun=true;
string input;
int arraysize=1;
int arrayindex=arraysize-1;
// in the array below I can put an arbitrary number so it wont get the segmentation fault but then I get the double free error instead
Todo *todoptr = new Todo[arraysize];
do
getline(cin,input);
switch (MenuChoice(input))
case '+':
cout << "plus loop\n"; //program runs this last line of code then crashes with double free error
if (firstrun==false)
arrayindex=arraysize-1;
Todo *tempptr = new Todo[arraysize];
for (int i = 0; i < arrayindex; i++)
tempptr[i]=todoptr[i];
//tempptr++;
tempptr[arrayindex].setData(input, arraysize);
//tempptr--;
delete[] todoptr;
Todo *todoptr = new Todo[arraysize+1];
for (int i = 0; i < arraysize; i++)
todoptr[i]=tempptr[i];
for (int i = 0; i < arraysize; i++)
todoptr[i].getData();
if (firstrun==true)
todoptr->setData(input, arraysize);
firstrun=false;
arraysize++;
break;
case '-':
break;
case '?':
break;
default:
cout << "Invalid entry. If you would like to quit, enter 'Q'";
string quit;
cin >> quit;
if (quit=="q" or quit=="Q")
menuloop=false;
break;
while(menuloop==true);
void ProgramGreeting()
cout << "Hello and welcome to my to do list maker!\n"
"Program Author: John Doe\n";
Date date;
cout << endl;
char MenuChoice(string input)
int n=input.length();
char charray[n+1];
strcpy(charray, input.c_str());
return charray[0];
【问题讨论】:
这个 sn-p 不会编译。请发minimal reproducible example 顺便说一句,为什么不使用std::vector<Todo>
而不是使用new
手动进行动态分配?
这会删除在循环外声明的指针:delete[] todoptr;
这会声明一个同名的新变量,它会遮蔽外部:Todo *todoptr = new Todo[arraysize+1];
循环中该行之前的所有内容都指向外部 @ 987654327@ 以及该行之后到循环末尾的所有内容都指的是新变量。您很可能只想在循环中使用todoptr = new Todo[arraysize+1];
,否则第二次迭代会尝试第二次删除相同的指针。
请注意,代码不是标准的 C++。 char charray[n + 1];
是一个可变长度数组。不要使用它们。请改用std::string
或std::vector<char>
。
MenuChoice
函数完全没有必要。 switch (input[0])
是一回事。在这两种情况下都应该首先检查!input.empty()
。
【参考方案1】:
有许多错误导致它崩溃。 例如:
变量阴影:有两个“Todo *todoptr”,这就是为什么会发生双重释放。 "outer todoptr" 在输入第三个 '+' 时没有有效指针。
for 循环中的赋值可能超出范围
【讨论】:
以上是关于为啥使用动态 ptr 数组检测到分段错误或双重释放?的主要内容,如果未能解决你的问题,请参考以下文章