C++ 赛格故障在哪里
C++ Where is the seg fault?
我目前正在为我的计算机科学课处理这项作业:
创建您自己的动态数组模板。它应该允许创建连续的数组(填充相同类型的东西(,您可以扩展这些数组而不必担心空间不足。
使用 malloc 做一个版本并免费。
使用新的和删除执行一个版本。
我使用new和delete的版本完美无缺;但是,在尝试将我的new/delete代码转换为使用malloc/free时,我不断遇到seg错误。我已经将段错误(我认为(缩小到一个函数:addData。看看我用来测试这个的主要代码:
Array2<int> *testArray3 = new Array2<int>(5);
Array2<int> *testArray4;
testArray3->initArray();
testArray3->printArray();
testArray4 = testArray3->addData(7);
testArray4->printArray();
return 0;
这给出了一个 seg 错误;但是,当我将其更改为以下错误时:
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
对象。我敢肯定会有例外,但不应该要求你这样做。我建议在这里使用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->data
和this->data
都指向同一内存。老实说,我不确定如果您两次释放相同的内存会发生什么,但我怀疑这是否好。无论如何,我认为你不想释放它。这将使this
处于破碎状态。
回顾和修复
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;
};
此版本保持不变,并返回一个比这更大的 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++调用模板函数错误。发布的解决方案解决了眼前的问题,但没有触及潜在的内存管理问题。
至于你班上的其他同学,我建议点击链接并回答什么是三法则?因为 Array2 违反了它。
- C++我需要了解在哪里使用指针和双指针
- 未定义的引用在哪里
- 谷歌测试中的期望值存储在哪里
- 尽管遵循了规则,内存泄漏在哪里
- 静态数据成员模板专用化的实例化点在哪里
- 在哪里放置我的函数?进入我的母语 Gui 还是进入我的演示者?
- 在哪里声明结构运算符重载
- C++ 中的自定义异常:在哪里定义它们?
- 常量参数存储在哪里 (C++)?
- 如何在 c++ 中确定一条指令(以字节为单位)在哪里结束,另一条指令从哪里开始?
- 此递归函数的每次迭代的值存储在哪里?
- 如何告诉本机节点模块所需的dll存储在哪里?
- 在哪里存储跨平台C++应用存储?
- C++泛型类错误,问题出在哪里?
- 在标准中,模板参数的语法在哪里定义,例如,'std::function<int(char)>'?
- 将类作为主要参数的语法在哪里需要?
- G :内部编译器错误:分割故障(程序CC1PLUS) - 我在哪里开始
- 知道分割故障在哪里比较两个文件
- C++ 赛格故障在哪里
- 不确定分割故障在哪里