C++:为什么我会出现此分段错误(可能发生在 main 之前?

C++: Why am I getting this segmentation fault (possibly occuring before main?)

本文关键字:可能发生 错误 main 之前 分段 为什么 C++      更新时间:2023-10-16

我刚刚完成了大部分(我想!)的调试,我的代码现在可以编译而没有任何错误。但是,当我尝试运行它时,它甚至在 main 的第一行之前返回一个段错误!我想知道这是否可能是内存问题,与我的结构定义中的字符串有关,但我什至还没有初始化它们,所以我不知道这将如何工作。我想的另一件事是,当我设置字符串时,也许我需要使用 new 运算符,但我的书以与我相同的方式声明字符串,据我所知(尽管他们的不是结构的一部分......

无论如何,这是我的代码!我们应该破解一些(大概真的很糟糕)密码,这些密码都使用相同的盐。

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <crypt.h>
using namespace std;
/* Read in a large, standard dictionary.
   Encrypt each word in the dictionary using the crypt() function
   Read in the password file and check each user's password to see
   whether it matches one of the dictionary entries
   Output the passwords for all of the accounts you have
   broken. */
struct ListNode{
  string user;
  string salt;
  string encrypted;
  string password;
  ListNode* next;
};

int main(){
  cout<<"Hello worldnn";
  /* Initializes singly linked list to hold user data */
  ListNode *root;
  ListNode *conductor;
  root = new ListNode;
  conductor = root;
  cout<<"After initializing listnn";
  string temp;
  //creates and opens filestream to password file
  ifstream psswdFile ("simplepsswd.txt");
  if(psswdFile.is_open()){
    //we assume there is at least one line, and initialize the head of
    //the list
    std::getline(psswdFile, conductor->user, ':');
    std::getline(psswdFile, conductor->salt, ':');
    std::getline(psswdFile, conductor->encrypted);
    //create first node
    //while there's more lines (store username in temp so we can
    //check)
    cout<< "Before password loopnn";
    while(std::getline(psswdFile, temp, ':')){
      //create next node
      conductor->next = new ListNode;
      conductor = conductor->next;
      conductor->next = NULL;
      //set data fields
      conductor->user = temp;
      //I know we don't NEED to store the salt but what if you decided
      //you wanted it later
      std::getline(psswdFile, conductor->salt, ':');
      std::getline(psswdFile, conductor->encrypted);
    }
  }
  //open the dictionary file
  ifstream dicFile("/usr/share/myspell/en_US.dic");
  string dicEntry;
  string dicEncrypted;
  if(dicFile.is_open()){
    int loc;
    //loop through words in dictionary
    cout<<"Before dictionary loopnn";
    while(std::getline(dicFile, dicEntry)){
      //check for weird flags and whatever.
      int loc = dicEntry.find('/');
      if(loc > 0){
    //if they're there, get rid of them!
    dicEntry.resize(loc);
      }
      //convert the entry to a c-string so we can use crypt on it
      char* cString;
      strcpy(cString, dicEntry.c_str());
      cString = crypt(cString, "AB");
      dicEncrypted = cString;
      //loop through the list comparing to encrypted passwords
      conductor = root;
      if(conductor->encrypted == dicEncrypted){
    conductor->password = dicEntry;
      }
      //password could occur more than once!
      while(conductor->next != NULL){
    conductor = conductor->next;
    if(conductor->encrypted == dicEncrypted){
      conductor->password = dicEntry;
    }
      }
    }
  }
  cout<<"Before print loopnn";
  conductor = root;
  if(conductor->password != ""){
    cout << "User " << conductor->user << "'s password is " << conductor->password << "nn";
  }
  while(conductor->next != NULL){
    conductor = conductor->next;
    if(conductor->password != ""){
      cout<<"User " << conductor->user << "'s password is " << conductor->password <<"nn";
    }
  }
  return 0;
}

好的,所以我尝试了评论中的一些东西,似乎我在创建第一个 ListNode 后就出现了段错误!

一个马上的问题是你正在写入一个未初始化的指针:

  //convert the entry to a c-string so we can use crypt on it
  char* cString;
  strcpy(cString, dicEntry.c_str());
  cString = crypt(cString, "AB");
  dicEncrypted = cString;

cString是一个未初始化的指针,指向谁知道在哪里。 然后使用 strcpy 函数将字符写入此内存地址。 这是未定义的行为,很可能是分段错误。

您必须分配内存,以便strcpy有空间写入字符串(加上终止 NULL)。

  char cString[100]; // or whatever number is large enough
  strcpy(cString, dicEntry.c_str());
  cString = crypt(cString, "AB");
  dicEncrypted = cString;

但即使这样也不安全,因为100可能没有足够的空间。 您需要发布crypt函数才能获得更可靠的答案。