简体   繁体   English

C ++类未正确初始化

[英]C++ Classes not initialized properly

I am working on a programming assignment for a class and am getting a really weird problem. 我正在为一个班级安排编程任务,并且遇到了一个非常奇怪的问题。 The technical problem is that I'm getting a seg fault when I try to do anything to a particular vector, but the object it's in and the object that object is in is also acting really weird. 技术问题是,当我尝试对特定向量执行任何操作时遇到段错误,但是该对象所在的对象以及该对象所在的对象的行为也确实很奇怪。 I suspect that it may be a simple syntax error that I don't know how best to solve, so let's start with that. 我怀疑这可能是一个简单的语法错误,我不知道如何最好地解决,所以让我们开始吧。 If this syntax is invalid or only semi-valid, you probably don't need to read the rest (unless changing it doesn't work). 如果此语法无效或仅是半有效的,则可能不需要读取其余语法(除非更改它不起作用)。

Anyway, here's the code I'm concerned about (in the addRel function of my Database.h file): 无论如何,这是我关注的代码(在我的Database.h文件的addRel函数中):

#ifndef DATABASE_H_
#define DATABASE_H_

#include "Parser.h"
#include "Relation.h"
#include <map>

class Database {
private:
  std::map<std::string, Relation> relations;
  std::stringstream out;
public:
  Database() {}
  ~Database() {}
  Relation* addRel(std::string RelName) {
    Relation* tmp = getRel(RelName);
    if(tmp == NULL) {
      relations.insert(std::pair<std::string, Relation> (RelName, Relation(RelName)));  //Is this a valid approach?
      tmp = getRel(RelName);
    }
    return tmp;
  }
  bool findRel(std::string RelName) {return getRel(RelName) != NULL;}
  Relation* getRel(std::string RelName) {return &relations.find(RelName)->second;}
  ...
};

I don't exactly want to create a Relation object in that function, but I need to have a Relation object to pass into relations.insert , so I just called the constructor for Relation in the function parameters. 我并不想在该函数中创建一个Relation对象,但是我需要有一个Relation对象才能传递给relations.insert ,因此我只是在函数参数中调用了Relation的构造函数。 If there's a better way to do this, that may be the cause of my grief, else I fear the worst, so here's a bunch of code and terminal output: 如果有更好的方法可以做到这一点,那可能是让我悲伤的原因,否则我会担心最坏的情况,因此这是一堆代码和终端输出:

Tuple.h (no .cpp): Tuple.h(无.cpp):

#ifndef TUPLE_H_
#define TUPLE_H_

#include <string>
#include <vector>

class Tuple : public std::vector<std::string> {};

//This approach was specifically encouraged by my instructor

#endif

Scheme.h (no .cpp): Scheme.h(无.cpp):

#ifndef SCHEME_H_
#define SCHEME_H_

#include "Tuple.h"
#include <utility>

class Scheme {
private:
  std::vector<std::string> attrs;
  std::string test;   //for testing purposes
public:
  Scheme() {
    attrs.clear();
    test = "This is a scheme.";
  }
  ~Scheme() {}
  void addAttr(std::string newAttr) {attrs.push_back(newAttr);}
  std::vector<std::string>* getAttrs() {return &attrs;}
  void clear() {attrs.clear();}
  std::string getTest() {return test;}
};

#endif

Relation.h (.cpp not relevant): Relation.h(.cpp不相关):

#ifndef RELATION_H_
#define RELATION_H_

#include "Scheme.h"
#include "Tuple.h"
#include <set>

class Relation {
private:
  std::string name;
  Scheme idents;
  ...
public:
  Relation(std::string newName) : name(newName) {}
  ~Relation() {}
  std::string getName() {return name;}
  Scheme* getScheme() {return &idents;}
  ...
};

#endif

Database.h (.cpp excerpt below): Database.h(下面的.cpp摘录):

#ifndef DATABASE_H_
#define DATABASE_H_

#include "Parser.h"
#include "Relation.h"
#include <map>

class Database {
private:
  std::map<std::string, Relation> relations;
  std::stringstream out;
public:
  Database() {}
  ~Database() {}
  Relation* addRel(std::string RelName) {
    Relation* tmp = getRel(RelName);
    if(tmp == NULL) {
      relations.insert(std::pair<std::string, Relation> (RelName, Relation(RelName)));  //Is this a valid approach?
      tmp = getRel(RelName);
    }
    return tmp;
  }
  bool findRel(std::string RelName) {return getRel(RelName) != NULL;}
  Relation* getRel(std::string RelName) {return &relations.find(RelName)->second;}
  ...
};

#endif

Database.cpp (the most interesting file): Database.cpp(最有趣的文件):

#include "Database.h"
#include <iostream>

using namespace std;

void Database::evalSchemes(vector<Predicate> schemes) {
  out << "Scheme Evaluation\n\n";
  for(unsigned int i = 0; i < schemes.size(); i++) {
    string name = schemes[i].getName();
    Relation* trel = addRel(name);
    Scheme* tsch = trel->getScheme();
    cout << "\nEvaluating scheme " << name << "\ni = " << i
      << "\ntrel is " << trel->getName() << "\ntsch = " << tsch
      << "\nTest = " << tsch->getTest() << "\n";
    tsch->clear();      //Segfaults here if this line is present
    std::vector<Parameter> tvec = schemes[i].getVector();
    for(unsigned int j = 0; j < tvec.size(); j++) {
      vector<string>* tattrs = tsch->getAttrs();
      string new_attr = tvec[j].getValue();
      cout << "\n\tAdding attribute " << new_attr << "\n\tj = " << j
        << "\n\tVector size = " << tattrs->size() << "\n";
      tsch->addAttr(new_attr);  //Segfaults here otherwise
    }
  }
}

...

Main.cpp: Main.cpp的:

#include "Scanner.h"
#include "Parser.h"
#include "Database.h"
#include <iostream>

using namespace std;

int main(int argc, char* argv[]) {
  if(argc < 3) {
    cout << "\nIncorrect program usage.\nPlease provide input and output file names.\n";
    return 0;
  }
  else {
    Scanner mainScanner(argv[1]);
    Parser mainParser;
    Database mainDatabase;
    mainScanner.scanAll();
    mainParser.importVector(mainScanner.getVector());
    mainParser.parseAll();
    DatalogProgram mainProg = mainParser.getProgram();

    //Everything up to this point works just fine

    mainDatabase.evalSchemes(mainProg.getSchemes());    //Segfaults during this function
    mainDatabase.evalFacts(mainProg.getFacts());
    mainDatabase.evalQueries(mainProg.getQueries());
    mainDatabase.output(argv[2]);
    return 0;
  }
}

And here's the output from the program. 这是程序的输出。 I'm running within gdb in Ubuntu 14.04 and ZSH, using g++ to compile, including the output of a backtrack. 我正在Ubuntu 14.04和ZSH中的gdb中运行,使用g ++进行编译,包括回溯的输出。 The second one has more information, so I've commented on the cout results of that program. 第二个有更多信息,因此我对该程序的提示结果进行了评论。

If I attempt to clear the vector before modifying it: 如果我尝试在修改向量之前将其清除:

(gdb) run in30.txt act30.txt
Starting program: /home/stephen/Dropbox/Code/CS_236/Lab3-Database/v1.0.1 in30.txt act30.txt

Evaluating scheme SK
i = 0
trel is @���� ����X����������� �����������������������������������
tsch = 0x7fffffffd878
Test = S

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b90350 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0  0x00007ffff7b90350 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x000000000040ac7a in std::_Destroy<std::string> (__pointer=0x0) at /usr/include/c++/4.8/bits/stl_construct.h:93
#2  0x0000000000409838 in std::_Destroy_aux<false>::__destroy<std::string*> (__first=0x0, 
    __last=0x7ffff7dc04e0 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+64>)
    at /usr/include/c++/4.8/bits/stl_construct.h:103
#3  0x00000000004070aa in std::_Destroy<std::string*> (__first=0x0, 
    __last=0x7ffff7dc04e0 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+64>)
    at /usr/include/c++/4.8/bits/stl_construct.h:126
#4  0x00000000004056c3 in std::_Destroy<std::string*, std::string> (__first=0x0, 
    __last=0x7ffff7dc04e0 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+64>)
    at /usr/include/c++/4.8/bits/stl_construct.h:151
#5  0x0000000000405ab8 in std::vector<std::string, std::allocator<std::string> >::_M_erase_at_end (this=0x7fffffffd878, __pos=0x0)
    at /usr/include/c++/4.8/bits/stl_vector.h:1352
#6  0x0000000000404688 in std::vector<std::string, std::allocator<std::string> >::clear (this=0x7fffffffd878)
    at /usr/include/c++/4.8/bits/stl_vector.h:1126
#7  0x00000000004038c8 in Scheme::clear (this=0x7fffffffd878) at Scheme.h:19
#8  0x0000000000401f81 in Database::evalSchemes (this=0x7fffffffd840, schemes=std::vector of length 1, capacity 1 = {...})
    at Database.cpp:15
#9  0x000000000040c57f in main (argc=3, argv=0x7fffffffe238) at Main.cpp:26
(gdb)

And here's what happens if I comment that line out: 如果我将这一行注释掉,将会发生以下情况:

(gdb) run in30.txt act30.txt
Starting program: /home/stephen/Dropbox/Code/CS_236/Lab3-Database/v1.0.1 in30.txt act30.txt

Evaluating scheme SK  //this is normal
i = 0                 //this is normal
trel is @���� ����X����������� �����������������������������������   //should be the relation's name
tsch = 0x7fffffffd878 //memory address, just to make sure it isn't NULL
Test = S              //should be "This is a scheme."

    Adding attribute A  //this is normal
    j = 0               //this is normal
    Vector size = 17592168972444  /should be 0; I haven't done anything with this vector yet

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b9146f in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0  0x00007ffff7b9146f in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00000000004098ca in __gnu_cxx::new_allocator<std::string>::construct<std::string<std::string const&> > (this=0x7fffffffd878, 
    __p=0x7ffff7dc04e0 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+64>)
    at /usr/include/c++/4.8/ext/new_allocator.h:120
#2  0x00000000004070ca in std::allocator_traits<std::allocator<std::string> >::_S_construct<std::string<std::string const&> >(std::allocator<std::string>&, std::allocator_traits<std::allocator<std::string> >::__construct_helper*, (std::string<std::string const&>&&)...) (__a=..., __p=0x7ffff7dc04e0 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+64>)
    at /usr/include/c++/4.8/bits/alloc_traits.h:254
#3  0x000000000040572e in std::allocator_traits<std::allocator<std::string> >::construct<std::string<std::string const&> >(std::allocator<std::string>&, std::string<std::string const&>*, (std::string<std::string const&>&&)...) (__a=..., 
    __p=0x7ffff7dc04e0 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+64>)
    at /usr/include/c++/4.8/bits/alloc_traits.h:393
#4  0x0000000000404528 in std::vector<std::string, std::allocator<std::string> >::push_back (this=0x7fffffffd878, __x="A")
    at /usr/include/c++/4.8/bits/stl_vector.h:905
#5  0x0000000000403893 in Scheme::addAttr (this=0x7fffffffd878, newAttr="A") at Scheme.h:17
#6  0x000000000040207a in Database::evalSchemes (this=0x7fffffffd840, schemes=std::vector of length 1, capacity 1 = {...})
    at Database.cpp:22
#7  0x000000000040c559 in main (argc=3, argv=0x7fffffffe238) at Main.cpp:26
(gdb)

Since the trel line doesn't quite look like it does in the terminal, here's a screen capture of that area of the output: 由于trel线看起来trel终端中的线,因此以下是该输出区域的屏幕截图:

终端输出

I would really appreciate absolutely any insight you can offer, as I'm at a complete loss, in part because I just don't know how to phrase the first mini-question into an effective Google search. 我非常感谢您提供的任何见解,因为我完全不知所措,部分原因是我不知道如何在有效的Google搜索中表达第一个小问题。 And if all you can answer is the first bit, that would still be absolutely fantastic. 如果您能回答的只是第一点,那绝对是很棒的。

My apologies if I'm way off, but I believe one problem may be in Database::getRel: 我很抱歉,如果我走了,但我相信一个问题可能出在Database :: getRel:

return &relations.find(RelName)->second;

The find function may return map:end if RelName isn't found, and map::end shouldn't be dereferenced. 如果未找到RelName,则find函数可能返回map:end,并且不应取消引用map :: end。 You should test for that possibility and return NULL manually in that case. 您应该测试这种可能性,并在这种情况下手动返回NULL。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM