【问题标题】:Why am I getting Segmentation Fault (core dumped) before main is even executed?为什么在 main 执行之前我会出现分段错误(核心转储)?
【发布时间】:2020-02-24 09:02:30
【问题描述】:

我有一个作业,我必须使用完美散列来对输入数组中的名称进行散列,并给出名称的数量。

这是我的代码:

字典.h

#include <string>
#include <vector>
using namespace std;

class Dictionary {
public:
    // Insert an input set of n keys to the dictionary. This method should print out the following information:
    // 1. The hash functions comprising the perfect hash (both levels)
    // 2. The sum of squares of the number of keys mapped to each bin of the first level hash function, and
    // 3. The number of trials needed to generate each hash function.
    void bulkInsert(int n, string *keys);

    // Insert a key to the dictionary.
    // Print out whether the insertion caused a collision in the second level hash.
    // Handle collision with separate chaining.
    void insert(string key);

    // Remove a key from the dictionary, if it exists.
    void remove(string key);

    // Return whether a key is found in the dictionary.
    // Print the buckets (both first and second level) accessed during the operation.
    bool find(string key);

    //make random matrix and print after
    void makeRandom(int nR, int nC);

    //format key and hash for first level, return index of hash
    int firstLevelHash(string input, int nR, int nC);

    //print hash
    void printHash();

private:
    vector<vector<int>> randomMat;
    vector<vector<int>> randomMat2;
    vector<vector<string>> hashTable;
};

字典.cpp

#include "Dictionary.h"
#include <iostream>
#include <string>
#include <cmath>
#include <bitset>
#include <cstdlib>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;

void Dictionary::bulkInsert(int n, string *keys) {

        int numRow = (ceil(log2(n)));
        int numCol = 64;
        int trialNum = 1;
        bool repeat = true;
        while ( repeat ) {

                //make random matrix
                makeRandom(numRow, numCol);

                //check hashtable empty, clear if not
                if ( !( hashTable.empty() ) ) {
                        hashTable.clear();
                }

                //create hashtable, given by 2^numRow
                for ( int i = 0; i < ( 2^numRow ); i++ ) {
                        vector<string> row;
                        hashTable.push_back(row);
                }

                //loop through keys and hash first level
                for ( int i = 0; i<n; i++) {

                        int ind = firstLevelHash(keys[i], numRow, numCol);

                        hashTable[ind].push_back(keys[i]);
                }

                //check condition on whether to repeat hash
                int limit = 4*n;
                int summation = 0;
                for ( int i = 0; i < hashTable.size(); i++ ) {
                        summation = summation + ((hashTable[i].size())^2);
                }
                if ( summation < limit ) {
                        repeat = false;
                }

                //second level hashing
        }
}

void Dictionary::insert(string key) {

}
void Dictionary::remove(string key) {

}

bool Dictionary::find(string key) {

        return false;
}

//randomizes randomMat and prints;
void Dictionary::makeRandom(int nR, int nC) {
        vector<int> row;
        for ( int i = 0; i < nR; i++ ) {
               row.clear();
               for ( int j = 0; j < nC; j++ ) {
                       int random = rand()%2;
                       row.push_back(random);
               }
               randomMat.push_back(row);
        }


}

//returns vector for key of length 64
int Dictionary::firstLevelHash(string input, int nR, int nC) {

        //check length of input
        //if less than 8, add space to front
        if ( input.size() < 8 ) {
                for( int p = 0; p < 8-(input.size()); p++) {
                        input = " " + input;
                }
        }

        //obtain string of length 64 of bits of input
        string binStr = "";
        for ( char& chr : input) {
                binStr += bitset<8>(chr).to_string();
        }

        vector<int> keyVector;

        //go through string and convert each to bit
        for ( int i = 0; i < binStr.size(); i++ ) {
                string substr = binStr.substr(i, 1);
                int val = stoi(substr);
                keyVector.push_back( val );
        }

        vector<int> hashFinalValue;

        //multiply by hash
        for ( int j = 0; j < nR; j++ ) {
                int hashVal = 0;
                for ( int p = 0; p < nC; p++ ) {
                        hashVal = hashVal + (randomMat[j][p] * keyVector[p]);
                }
                hashVal = hashVal % 2;
                hashFinalValue.push_back( hashVal );
        }

        //convert binary to decimal to get index
        int index = 0;
        int q = 1;
        for ( int m = 0; m < hashFinalValue.size(); m++ ) {
                index += hashFinalValue[m] * ( 2^(hashFinalValue.size()-q) );
                q++;
        }

        return index;
}

//prints hashTable
void Dictionary::printHash() {

        for ( int i = 0; i < hashTable.size(); i++ ) {

                for ( int j = 0; j < hashTable[i].size(); j++ ) {
                        cout << hashTable[i][j];
                        cout << " | ";
                }

                cout << "\n";
        }

}

my_test_dictionary.cpp

#include "Dictionary.h"
#include <iostream>
using namespace std;

int main(){
        cout<<"adfad";
        Dictionary dict;

        string strs[] = {"Fred Astaire", "Lauren Bacall", "Brigitte Bardot", "John Belushi", "Ingmar Bergman"};
        int n = 5;

        dict.bulkInsert(n, strs);

        dict.printHash();

        return 0;
}

当我使用 g++ Dictionary.cpp my_test_dictionary.cpp 编译时,我立即得到“Segmentation fault (core dumped)”,并且根本没有打印 main 第一行的“adfad”。

请帮忙。我坏了。

【问题讨论】:

  • 你调试了吗?或者你是否假设段错误发生在 main 之前只是因为之前没有输出“adfad”?如果是后者,请调试。还可以添加换行符或刷新以强制在该行中输出,而不是更晚。
  • 进行调试构建并且不进行优化
  • OT:using namespace std; 代表源文件中的一种非常糟糕的做法,以及头文件中的一种邪恶做法。
  • 打印输出到std::cout 是缓冲的,如果发生段错误(通常由 UB 引起)则不需要打印。
  • 2^numRow 很可能不是您的意思。与((hashTable[i].size())^2相同

标签: c++ segmentation-fault global-variables


【解决方案1】:

您关于程序在到达main 之前失败的断言是错误的。事实上,它在这里崩溃了:

#0  0x00007ffff7f60484 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x0000555555558783 in __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (this=0x5555555742b0, __p=0x31, 
    __args#0="Lauren Bacall") at /usr/include/c++/8/ext/new_allocator.h:136
#2  0x00005555555579ce in std::allocator_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (__a=..., __p=0x31, 
    __args#0="Lauren Bacall") at /usr/include/c++/8/bits/alloc_traits.h:475
#3  0x00005555555570ea in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (this=0x5555555742b0, __x="Lauren Bacall") at /usr/include/c++/8/bits/stl_vector.h:1079
#4  0x000055555555650b in Dictionary::bulkInsert (this=0x7fffffffdb40, n=5, keys=0x7fffffffdaa0) at Dictionary.cc:39
#5  0x000055555555af9c in main () at my_test_dictionary.cc:12

如果您在调试器下运行程序,您会很容易发现这一事实。

您看不到 adfad 输出的原因与已经正确指出的缓冲(如 Daniel Langr)有关。

要解决缓冲问题,请在添加“调试打印”时始终使用std::cerr

现在,实际崩溃的原因有点难以发现(但 Botje 确实正确地发现了它)。这个循环:

 //create hashtable, given by 2^numRow
 for ( int i = 0; i < ( 2^numRow ); i++ ) {

只执行一次,而不是您预期的 8 次。解释见this answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 2017-01-26
    相关资源
    最近更新 更多