繁体   English   中英

调用 class 构造函数时出现分段错误

[英]Segmentation fault when calling a class constructor

我正在尝试为符号表的特定实现实例化 class ,并且按照项目的说明,我通过指针进行操作。 我的构造函数做了很多事情,因为它是从文本文件构建符号表的事情,但是我在构造函数的末尾遇到了分段错误错误。 我不明白到底是什么给了我这个错误。 我做了一些调试,似乎我的构造函数运行得很好,因为它到达了我放在最后一个括号的断点,并且所有数据都在我预期的向量中。 但是,当它尝试退出构造函数并返回主文件时,它给了我这个错误。

主文件如下:

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string.h>
#include <time.h>
using namespace std;

#include "tabeladesimbolos.hpp"
typedef char * String;
typedef int * Integer;


int main(int argc, char *argv[])
{
    fstream arqTexto;

    /* abra arquivo com texto */
    arqTexto.open(argv[1]);

    if (arqTexto.fail())
    {
        cout << "ERRO: arquivo" << argv[1] << "nao pode ser aberto.\n";
        exit(EXIT_FAILURE);
    }

    arqTexto.close();

    string nome_arquivo = argv[1];

    /* crie a ST*/
    cout << "criando ST...\n";

    /* usadas para medir tempo de processamento */
    clock_t start, end;
    double elapsed = 0;

    start = clock();
    vetorDes *st = new vetorDes(nome_arquivo);
    end = clock();

    /* calcule o tempo */
    elapsed = ((double)(end - start)) / CLOCKS_PER_SEC;
    cout << "arquivo lido e ST construida em " << elapsed << " segundos\n";

    delete st;

    return 0;
}

错误发生在以下行:

vetorDes *st = new vetorDes(nome_arquivo);

带有构造函数 (tabeladesimbolos.hpp) 的文件是:

#include <string>
#include <string.h>
#include <iostream>
#include <fstream>
#include <vector>

typedef char * String;
typedef int * Integer;
using namespace std;

struct Valor
{
    String chave;
    Integer valor;
};

class vetorDes
{
    vector<Valor> vetor;

public:
    vetorDes(string nomeArquivo);
    void insere(String chave, Integer valor);
    Integer devolve(String chave);
};

vetorDes::vetorDes(string nomeArquivo)
{
    ifstream arqTexto;
    String palavra;
    Integer aux = nullptr;
    vetor.reserve(10000);
    arqTexto.open(nomeArquivo);
    while (arqTexto >> palavra)
    {
        aux = devolve(palavra);
        if (aux == nullptr)
        {
            int* um = new int;
            *um = 1;
            insere(palavra, um);
        }
        else
        {
            (*aux)++;
        }
    }
}

void vetorDes::insere(String chave, Integer valor)
{
    Valor *aux = new Valor;
    aux->chave = (String) malloc(20*sizeof(char));
    strcpy(aux->chave, chave);
    aux->valor = valor;
    int maxsize = vetor.max_size();
    int currentsize = vetor.size();
    vetor.push_back(*aux);
    return;
}

Integer vetorDes::devolve(String chave)
{
    for (std::size_t i = 0; i < vetor.size(); ++i)
    {
        String teste = vetor[i].chave;
        if (!strcasecmp(teste, chave))
        {
            return vetor[i].valor;
        }
    }
    return nullptr;
}

我的调试器将我带到构造函数中的最后一个 } 而没有错误,这让我相信问题出在我分配某些东西的方式上,因为它仅在程序尝试完成“new vetorDes”调用时出现。

完整的错误信息是:

Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x3b002e6f746e6174) at malloc.c:3103

我究竟做错了什么? 我错过了什么?

__GI___libc_free (mem=0x3b002e6f746e6174)

0x3b002e6f746e6174显然是无效指针:

  • 它不是规范形式
  • 它的尾巴看起来像ASCII字符串tanto.

可以安全地假设您有某种堆溢出(或其他堆损坏)。 使用ValgrindAddress Sanitizer查找错误。

正如 NM 所指出的,通过将指针隐藏在这些 typedef 后面,您对自己造成了极大的伤害:

typedef char * String;
typedef int * Integer;

如果您不这样做,该错误会更加明显:

char *palavra;  // uninitialized pointer
...
while (arqTexto >> palavra) // BUG: writes to random memory
String palavra; 
...
while (arqTexto >> palavra)

在声明 palavra(它是一个指针)和读入它之间,我没有看到任何东西,这使得 palavara 指向任何地方。 指针未初始化,因此它指向某个随机位置,而您正在将数据读入该随机位置。 那时任何事情都可能发生,除了好的事情。

暂无
暂无

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

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