不确定在哪里放置我的删除函数,以避免出现分段错误?

huangapple go评论83阅读模式
英文:

Not sure where to put my delete function without getting a segmentation fault?

问题

以下是代码部分的翻译:

我有一个名为 MyObject 的对象,其中包含成员变量,用于保存名称(这是重载构造函数设置的内容)和一个字符数据的链接列表。我从一个文件中读取了一堆以以下格式存储的 MyObjects

name,a,b,c,d
name1,a,b,c,d,e
// 等等

我的代码应该获取每个对象并将其添加到 myVect 中:

vector<MyObject*> myVect;

我的问题是,我使用 new 来分配内存。当然,我知道这意味着我需要使用 delete(而当我没有使用 delete 时,会导致内存泄漏,因此我不认为这是双重删除问题),但无论我在何处删除 ptr,都会导致分段错误。

我希望 myVect 不仅仅保存指针,但由于需要进行赋值,所以必须这样做。

以下是代码:

void Sequencer::ReadFile() {
  ifstream fin;
  fin.open(fileName);
  cout << "打开文件" << endl;
  string line = "";
  MyObject* ptr;
  while(getline(fin, line)) {
    string name = "";
    int count = 0;
    while(line[count] != ',') {
      name += line[count];
      count++;
    }
    ptr = new MyObject(name);
    for(int i = count + 1; i < line.size(); i+=2) {
      (*ptr).InsertEnd(line[i]);
    }
    myVect.push_back(ptr);
    //delete ptr;                                                               
    //ptr = nullptr;                                                            
  }
  //delete ptr;                                                                  
  //ptr = nullptr;                                                               
  fin.close();
}

请注意,这是您提供的代码的翻译部分,不包括其他内容。

英文:

I have an object MyObject with member variables that hold a name (which is what the overloaded constructor sets and a linked list of character data. I read in from a file that has a bunch of MyObjects in the following format:

name,a,b,c,d
name1,a,b,c,d,e
// etc.

My code is supposed to grab each object and add it to myVect
vector&lt;MyObject*&gt; myVect;

My problem is that I use new to allocate. Of course I know this means I need delete (and when I don't have delete there are memory leaks so I don't think this a double deletion issue), but no matter where I delete ptr, it cause a segmentation fault.

I would love for myVect to not hold pointers but it has to (assignment).

Here's the code

void Sequencer::ReadFile() {
  ifstream fin;
  fin.open(fileName);
  cout &lt;&lt; &quot;Opened File&quot; &lt;&lt; endl;
  string line = &quot;&quot;;
  MyObject* ptr;
  while(getline(fin, line)) {
    string name = &quot;&quot;;
    int count = 0;
    while(line[count] != &#39;,&#39;) {
      name += line[count];
      count++;
    }
    ptr = new MyObject(name);
    for(int i = count + 1; i &lt; line.size(); i+=2) {
      (*ptr).InsertEnd(line[i]);
    }
    myVect.push_back(ptr);
    //delete ptr;                                                               
    //ptr = nullptr;                                                            
  }
  //delete ptr;                                                                 
  //ptr = nullptr;                                                              
  fin.close();
}

答案1

得分: 1

记住,你不应该delete指针,而应该delete指针指向的对象。这意味着在ReadFile中的任何地方都不应该delete ptr,因为你希望指向的对象在myVect 持有指针的整个生存期内都继续存在。

相反,你应该在myVect中的指针指向的每个对象完成后进行delete操作。最常见的地方是在myVect所属的对象的析构函数中。例如:

Sequencer::~Sequencer() {
    for (MyObject* p : myVect) {
        delete p;
    }
}

当然,如果你使用智能指针而不是裸指针,那么你就不需要手动delete任何东西。例如,myVect可以是std::vector<std::unique_ptr<MyObject>>。在这种情况下,unique_ptr 在其生命周期结束时会自动delete它们指向的对象。

在这种情况下,你需要将ReadFile更改为以下内容:

void Sequencer::ReadFile() {
  std::ifstream fin(fileName);
  std::string line = "";
  while(std::getline(fin, line)) {
    std::string name = "";
    int count = 0;
    while(line[count] != ',') {
      name += line[count];
      count++;
    }
    std::unique_ptr<MyObject> ptr = std::make_unique<MyObject>(name);
    for(int i = count + 1; i < line.size(); i+=2) {
      ptr->InsertEnd(line[i]);
    }
    myVect.push_back(ptr);
  }
}

前提是你是否真的需要使用指针。你当前的ReadFile实现没有特殊原因来动态分配对象。如果可能的话,最好的解决方案是让myVect成为std::vector<MyObject>,并让std::vector自己处理所有对象的生命周期:

void Sequencer::ReadFile() {
  std::ifstream fin(fileName);
  std::string line = "";
  while(std::getline(fin, line)) {
    std::string name = "";
    int count = 0;
    while(line[count] != ',') {
      name += line[count];
      count++;
    }
    MyObject obj(name);
    for(int i = count + 1; i < line.size(); i+=2) {
      obj.InsertEnd(line[i]);
    }
    myVect.push_back(obj);
  }
}
英文:

Remember, you do not delete pointers, you delete the thing a pointer points to. That means that it doesn't make sense to delete ptr anywhere in ReadFile, since you want the pointed-to objects to continue to exist for as long as myVect holds pointers to them.

Instead you want to delete each object pointed to by the pointers in myVect whenever you're finished with them. The most common place for that is in the destructor of the object that myVect is a member of. For example:

Sequencer::~Sequencer() {
    for (MyObject* p : myVect) {
        delete p;
    }
}

Of course, if you just used smart pointers instead of raw pointers then you wouldn't need to manually delete anything. For instance, myVect could be a std::vector&lt;std::unique_ptr&lt;MyOjbect&gt;&gt;. In that case the unique_ptrs would automatically delete the object they point to when their lifetime ends.

In that case you would change ReadFile to something like this:

void Sequencer::ReadFile() {
  std::ifstream fin(fileName);
  std::string line = &quot;&quot;;
  while(std::getline(fin, line)) {
    std::string name = &quot;&quot;;
    int count = 0;
    while(line[count] != &#39;,&#39;) {
      name += line[count];
      count++;
    }
    std::unique_ptr&lt;MyObject&gt; ptr = std::make_unique&lt;MyObject&gt;(name);
    for(int i = count + 1; i &lt; line.size(); i+=2) {
      ptr-&gt;InsertEnd(line[i]);
    }
    myVect.push_back(ptr);
  }
}

That's all assuming you need pointers at all. Your current ReadFile implementation doesn't have any particular reason to dynamically allocate objects. If possible, the best solution would be to just have myVect be a std::vector&lt;MyObject&gt; and let std::vector handle all of the objects' lifetimes itself:

void Sequencer::ReadFile() {
  std::ifstream fin(fileName);
  std::string line = &quot;&quot;;
  while(std::getline(fin, line)) {
    std::string name = &quot;&quot;;
    int count = 0;
    while(line[count] != &#39;,&#39;) {
      name += line[count];
      count++;
    }
    MyObject obj(name);
    for(int i = count + 1; i &lt; line.size(); i+=2) {
      obj.InsertEnd(line[i]);
    }
    myVect.push_back(obj);
  }
}

huangapple
  • 本文由 发表于 2023年4月4日 12:20:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75925489.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定