gpt4 book ai didi

C++ 段错误在哪里?

转载 作者:搜寻专家 更新时间:2023-10-31 02:20:16 24 4
gpt4 key购买 nike

我目前正在为我的计算机科学课处理这项作业:

制作您自己的动态数组模板。它应该允许创建连续的数组(填充相同类型的东西),您可以扩展它们而不必担心空间不足。

使用 malloc 和 free 做一个版本。

使用 new 和 delete 执行一个版本。

我使用 new 和 delete 的版本完美无缺;但是,在尝试将我的新/删除代码转换为使用 malloc/free 时,我不断遇到段错误。我已经将段错误(我认为)缩小到一个函数中:addData。看看我用来测试这个的主要代码:

Array2<int> *testArray3 = new Array2<int>(5);
Array2<int> *testArray4;
testArray3->initArray();
testArray3->printArray();
testArray4 = testArray3->addData(7);
testArray4->printArray();

return 0;

这给出了一个段错误;但是,当我将其更改为:
Array2<int> *testArray3 = new Array2<int>(5);
Array2<int> *testArray4;
testArray3->initArray();
testArray3->printArray();
testArray4 = testArray3; //->addData(7);
testArray4->printArray();
return 0;

没有段错误。这让我相信问题出在我的 addData 函数中。这是代码:
Array2<T> *addData(T dataToAdd){
Array2 <T> *tmp;
tmp->data = this->getData();
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));

for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}

free(tmp->data);
free(this->data);
return newData;
};

我是一个整体编程新手,还没有完全理解指针和内存分配等问题。您能给我的任何建议将不胜感激!如果您需要查看其余代码,这里是我编写模板的整个文件。非常感谢您抽出宝贵时间!
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
using namespace std;

template<typename T>
class Array2{
public:
Array2(int size){
this->size = size;
data = (T *) malloc(sizeof(T)*size);

};
Array2<T> *addData(T dataToAdd){
Array2 <T> *tmp;
tmp->data = this->getData();
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));

for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}

free(tmp->data);
free(this->data);
return newData;
};
~Array2(){
free(this->data);
};
void initArray(){
for (int i = 0; i < this->size; ++i){
//this->data[i] = i;
this->setData(i, i);
}
};
void printArray(){
//ostringstream oss;
string answer = "";

for (int i = 0; i < this->size; ++i){
//oss << this->data[i] + " ";
cout << this->data[i] << " ";
}

//answer = oss.str();

cout << answer << endl;
};
T* getData(){
return this->data;
}
int getSize(){
return this->size;
}
void setData(T data, int index){
this->getData()[index] = data;
}
private:
int size;
T* data;
};

最佳答案

Array2 <T> *tmp;

分配一个指针。这不会将指针指向任何东西,也不会为指向的指针分配任何存储空间。它在没有明确分配的情况下指向的内容是未定义的。如果你很幸运,这次你是,tmp 指向一个无效的位置,程序就会崩溃。如果你不走运,tmp 会指向程序内存的某个可用区域并让你重写它,从而破坏那里的任何信息。
tmp->data = this->getData();

尝试在 tmp 访问数据成员,但幸运的是,访问位于无效内存中,程序停止。它也有 tmp 的数据指向这个数据,这是一个危险的位置。对一个的更改将发生在另一个上,因为它们都使用相同的存储。还要考虑一下如果释放 tmp->data 会发生什么事情。

或者也许我错了,出于同样的原因,这里停止了:
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));

两者都需要修复。 tmp 不一定要长寿,所以我们可以把它设为一个临时的局部变量。
Array2 <T> tmp;

通常这将在堆栈上创建并在函数结束并且 tmp 超出范围时销毁。

但这不起作用,因为 Array2 的构造函数需要一个大小,以便它可以分配数组的存储空间。你需要弄清楚它有多大。大概是这样的:
Array2 <T> tmp(this->size + 1);

但坦率地说,我认为你根本不需要 tmp。您应该能够将 dataToAdd 直接复制到 newData 中,而无需使用 tmp 作为中介。

newData 最终将返回给调用者,因此它需要更长的范围。使用时间 new .
Array2 <T> *newData = new Array2 <T>(this->size + 1);

并通过构造函数的魔力...等一下。无法使用 new .这使得这很难。 malloc不调用构造函数,所以虽然 malloc将为 newData 分配资源,它不会做繁重的工作来正确设置 newData。经验法则是从不 malloc一个东西。我敢肯定会有异常(exception),但你不应该被要求这样做。我推荐使用 new在这里,如果他们提示的话,礼貌地告诉教练他们正在努力。

无论如何, new Array2 <T>(this->size + 1)将分配 data用它的构造函数为你存储。

有一种更简单的方法可以做到这一点
for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}

尝试:
for (int i = 0; i < tmp->size; ++i){
newData->data[i] = tmp->data[i]; // you were right here
}
newData->data[tmp->size] = dataToAdd;

回到我之前暗示的东西:
free(tmp->data);
free(this->data);

两个 tmp->datathis->data指向同一个内存。老实说,我不确定如果两次释放相同的内存会发生什么,但我怀疑这是否好。无论如何,我认为您不想释放它。那将离开 this处于 splinter 状态。

回顾和修复
Array2<T> *addData(T dataToAdd)
{
Array2 <T> *newData = new Array2 <T>(this->size + 1);

for (int i = 0; i < this->size; ++i)
{
newData->data[i] = this->data[i];
}
newData->data[this->size] = dataToAdd;

return newData;
};

这个版本保持原样并返回一个比这个大的新数据。它没有做的是添加任何东西。这对于名为 addData 的方法来说是愚蠢的。

它也会导致这样的事情:
mydata = myData->addData(data);

这会泄漏内存。原来的mydata没有删除就丢失了,导致内存泄露。

我认为您真正需要的要简单得多:
Array2<T> & addData(T dataToAdd)
{
this->data = realloc(this->data, this->size + 1);
this->data[this->size] = dataToAdd;
this->size++;
return *this;
};

realloc有效地分配一个新缓冲区,将旧缓冲区复制到新缓冲区中,然后一举释放旧缓冲区。时髦的。

然后我们添加新元素并增加存储元素的数量。

最后,我们返回一个对对象的引用,以便它可以在链中使用。

用法可以
myData.addData(data);
myData.addData(data).addData(moredata);
myData.addData(data).printArray();

如果你有运营商 << 支持写
std::cout << myData.addData(data) << std::endl;

我会回到 new如果我是你的话,Array 的版本。这里挑选的大多数错误都是概念性错误,也适用于它。你可能只是变得不走运,它只是看起来有效。我刚读了 C++ Calling Template Function Error .发布的解决方案解决了眼前的问题,但没有触及底层的内存管理问题。

至于你类的其他人,我建议点击链接并回答 What is The Rule of Three?因为 Array2 违反了它。

关于C++ 段错误在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32916683/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com