我在以下代码(指针)上收到 SIGSEGV 错误,不知道哪里出错了

Posted

技术标签:

【中文标题】我在以下代码(指针)上收到 SIGSEGV 错误,不知道哪里出错了【英文标题】:I am receiving a SIGSEGV error on the following code (pointers) and don't know where I am going wrong 【发布时间】:2021-04-12 06:42:48 【问题描述】:

这是我正在构建的代码(对我的作业进行解释):

/*
  Proposal:
    Create a list-based graph representation.

    It will need to support the following operations.
      1. Ask the user how many Vertices there are.

      2. Ask the user to label those Vertices, ie "A", "B", "C"...

      3. Define the graph as an array of linked lists based on the number of
      Vertices that hold labels. The node type would support the label and weight.

      4. Repeatedly ask the user to define edges between two Vertices with the weight of the edge. Add these edges to the list.

      5. Have a list method that will list out all of the edges in the graph
      with their weights.

  Sample Run:
  N/A
*/
#include <iostream>
#include <cstdlib>
#include <string>


// ========== Struct Definition(s) ==========
struct AdjListNode 
  int dest;
  std::string label;
  int weight;

  struct AdjListNode* next;
;


struct AdjList 
  struct AdjListNode *head;
;


// ===== Class Definition(s) ==========
class Graph 
  private:

    int num;
    struct AdjList* array;

  public:
    std::string *a;

    Graph(int);

    void addEdge(int, int, int, std::string, std::string);
    void label(std::string,int);
    void output();

    AdjListNode* newAdjListNode(int point, int weight, std::string labelname) 
      AdjListNode* newNode = new AdjListNode;

      newNode->dest = point;
      newNode->weight = weight;
      newNode->label = labelname;
      newNode->next = NULL;

      return newNode;
    
;


// ========== Function Prototype(s) ==========
// In Class(es)


// ========== Main Function ==========
int main() 
  int num, distance, choice, head, tail;
  std::string input;

  std::cout << "Enter the number of vertices: ";
  std::cin >> num;

  Graph graph(num);

  std::cout << "\nPlease label the vertices ('A', 'B', 'C', etc.)\n";

  for (int i = 0; i < num; i++) 
    std::cout << "Label for vertex " << (i+1) << ": ";
    std::cin >> input;

    graph.label(input, i);
  

  for (int i = 0; i < num; i++) 
    std::cout << "\nEnter two edges between " << "OUTPUT i and i+1 vertices (e.g. 1 5): ";
    std::cin >> head >> tail;

    std::cout << "Enter the weight of this edge: ";
    std::cin >> distance;

    graph.addEdge(head, tail, distance, graph.a[head], graph.a[tail]);
  

  graph.output();

  return 0;



// ========== Function Definition(s) ==========
Graph::Graph(int num) 
  this->num = num;

  array = new AdjList [num];
  a = new std::string [num];

  for (int i = 0; i < num; ++i) 
    array[i].head = NULL;
  



void Graph::addEdge(int a, int b, int weight, std::string bname, std::string tname) 
  if( a >= num || b >= num || a < 0 || b < 0) 
    std::cout << " Input is invalid\n";
  

  else 
    AdjListNode* newNode = newAdjListNode(b,weight, tname);

    newNode->next = array[a].head;
    array[a].head = newNode;
    
    newNode = newAdjListNode(a,weight, bname);
    newNode->next = array[b].head;
    array[b].head = newNode;
  



void Graph::label(std::string b, int i) 
  a[i] = b;



void Graph::output() 
  std::string input;

  for (int i = 0; i < num; i++) 
    AdjListNode* list = array[i].head;
    std::cout << "\nAdjacency list of the vertex " << i << " with labeled name: " << a[i];

    while (list) 
      std::cout << list->dest << " with the labeled name " << list->label << " and the weight being " << list->weight << "\n";
      list = list->next;
    

    std::cout << "\n";
  

点击此行时我收到错误:graph.addEdge(head, tail, distance, graph.a[head], graph.a[tail]);,但是,我怀疑问题出在我的类定义及其设置方式中。

有人可以在这里给我一些帮助吗?

我正在运行代码here (onlinegdb)

阻止我的是我稍微了解 SIGSEGV 错误是什么,但我只是看不到我错误地尝试访问内存的位置。调试器显示graph 具有以下内容 -> num = 2, array = 0x614c20, a = 0x614c48,但内存中的这些点应该可以访问,因为我保留它们,不是吗?

澄清graph 值 - 我正在输入 2 个顶点,对于前 2 个边,我正在输入带有权重的 15 5

这是我运行程序时的确切 I/O:

Enter the number of vertices: 2                                                                                                                                     
                                                                                                                                                                    
Please label the vertices ('A', 'B', 'C', etc.)                                                                                                                     
Label for vertex 1: A                                                                                                                                               
Label for vertex 2: B                                                                                                                                               
                                                                                                                                                                    
Enter two edges between OUTPUT i and i+1 vertices (e.g. 1 5): 1 5                                                                                                   
Enter the weight of this edge: 2                                                                                                                                    
Segmentation fault (core dumped)                                                                                                                                    
                                                                                                                                                                    
                                                                                                                                                                    
...Program finished with exit code 139                                                                                                                              
Press ENTER to exit console.

【问题讨论】:

这个输入有什么问题:wandbox.org/permlink/PyzdA8jJLSXX5l1K “我开始认为 onlinegdb 有问题,而不是我的代码” 您可以确定这是您的代码有问题。这可能是代码中某处未定义的行为(读取/写入越界,读取未初始化的值,...) 您将tail 设置为5 并且在Graph::addEdge 中您有array[b].head;array[5].head;array 有两个元素。 array[5] 是越界访问。您应该使用std::vectorstd::vector::at 而不是operator[] 来查找这些问题。 您有内存泄漏。您的代码应该为每个new 包含一个delete。使用 STL 容器来避免此类泄漏。 @PythonReactor std::string *a; -- 为什么这是一个指针?为什么不简单地std::vector&lt;std::string&gt; a; 【参考方案1】:

graph.a 有两个元素,但 tail 设置为 5graph.a[tail] 是越界访问。它会导致未定义的行为。

您应该避免动态内存分配并改用std::vectorstd::vector 提供std::vector::at 来帮助查找这些错误。你用性能来支付它。 std::vector::at 增加了范围检查,速度有点慢,但搜索错误会让你变慢。

#include <iostream>
#include <string>
#include <vector>

struct AdjListNode 
  int dest;
  std::string label;
  int weight;

  AdjListNode* next;
;

struct AdjList 
  AdjListNode *head;
;

class Graph 
  private:

    int num;
    std::vector<AdjList> array;

  public:
    std::vector<std::string> a;

    Graph(int);

    void addEdge(int, int, int, std::string, std::string);
    void label(std::string,int);
    void output();

    AdjListNode* newAdjListNode(int point, int weight, std::string labelname) 
      AdjListNode* newNode = new AdjListNode;

      newNode->dest = point;
      newNode->weight = weight;
      newNode->label = labelname;
      newNode->next = nullptr;

      return newNode;
    
;

int main() 
  int num, distance, head, tail;
  std::string input;

  std::cout << "Enter the number of vertices: ";
  std::cin >> num;

  Graph graph(num);

  std::cout << "\nPlease label the vertices ('A', 'B', 'C', etc.)\n";

  for (int i = 0; i < num; i++) 
    std::cout << "Label for vertex " << (i+1) << ": ";
    std::cin >> input;

    graph.label(input, i);
  

  for (int i = 0; i < num; i++) 
    std::cout << "\nEnter two edges between " << "OUTPUT i and i+1 vertices (e.g. 1 5): ";
    std::cin >> head >> tail;

    std::cout << "Enter the weight of this edge: ";
    std::cin >> distance;

    graph.addEdge(head, tail, distance, graph.a.at(head), graph.a.at(tail));
  

  graph.output();

  return 0;


Graph::Graph(int num) : array(num), a(num) 
  this->num = num;

  for (int i = 0; i < num; ++i) 
    array.at(i).head = nullptr;
  


void Graph::addEdge(int a, int b, int weight, std::string bname, std::string tname) 
  if( a >= num || b >= num || a < 0 || b < 0) 
    std::cout << " Input is invalid\n";
   else 
    AdjListNode* newNode = newAdjListNode(b,weight, tname);

    newNode->next = array.at(a).head;
    array.at(a).head = newNode;
    
    newNode = newAdjListNode(a,weight, bname);
    newNode->next = array.at(b).head;
    array.at(b).head = newNode;
  


void Graph::label(std::string b, int i) 
  a.at(i) = b;


void Graph::output() 
  std::string input;

  for (int i = 0; i < num; i++) 
    AdjListNode* list = array.at(i).head;
    std::cout << "\nAdjacency list of the vertex " << i << " with labeled name: " << a.at(i);

    while (list) 
      std::cout << list->dest << " with the labeled name " << list->label << " and the weight being " << list->weight << "\n";
      list = list->next;
    

    std::cout << "\n";
  

抛出异常:

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 5) >= this->size() (which is 2)

【讨论】:

非常感谢。我觉得自己像个傻瓜——我意识到这不是对图表的理解,而是代码的问题(有点)。我现在看到您在尝试将尾部设置为超出可用顶点数的索引时所说的内容。这在很多方面非常很有帮助。

以上是关于我在以下代码(指针)上收到 SIGSEGV 错误,不知道哪里出错了的主要内容,如果未能解决你的问题,请参考以下文章

什么导致 SIGSEGV

应用程序启动时的Android SIGSEGV异常

Android Studio Emulator崩溃:进程以退出代码139结束(由信号11中断:SIGSEGV)

原生Android应用程序中的SIGSEGV错误

“程序收到信号SIGSEGV,分段错误”当试图使用递归获取3个字符组合的所有关键字时

当我尝试从双向链表中删除最后一个元素时,为啥会收到“信号 SIGSEGV,分段错误”?