c++ - 与文件 i/o 相关的 c++ 程序末尾的段错误

标签 c++ file-io segmentation-fault

我正在从事一个密码学项目,我们的密码需要能够读取和写入文件。我的一个合作伙伴实现了读取功能,现在我们遇到了一个奇怪的问题。如果用户没有提供输出文件,我们的程序运行正确且没有错误,但如果提供了输出文件,则在完成后(返回 0)会出现段错误。但是,该程序仅在我的机器上出现段错误。我的团队成员正在运行 OS X 和 Fedora,而我正在运行 Ubuntu,如果这很重要的话。我们所有人都在使用 c++11 进行编译,尽管我在技术上指定了 c++0x。

int main(int argc, char** argv)
 {
   std::string usageWarning =  "usage: [-i/--input fileName] [-o/--output fileName] 
   [-        k/--key 32bitKey] [-n/--nonce numEncryptions]";
   int nonce = 1;
   std::string inputFile;
   std::string outputFile;
   std::string key;
   bool hasInputFile = false;
   bool hasOutputFile = false;    
   bool hasKey = false;
   std::ofstream out;

   if (argc < 2) {
    std::cerr << usageWarning << std::endl;
    return 1;
   }

  //Parse command line input
  for( int i = 1; i < argc; i++ ) {
    if (0 == strncmp(argv[i], "-n", 2) || 0 == strncmp(argv[i], "--nonce", 7)) {
      i = i + 1;
      nonce = std::stof(argv[i]);
    }
    else if (0 == strncmp(argv[i], "-i", 2) || 0 == strncmp(argv[i], "--input", 7)) {
      i = i + 1;
      inputFile = argv[i];
      hasInputFile = true;
    }
    else if (0 == strncmp(argv[i], "-o", 2) || 0 == strncmp(argv[i], "--output", 8)) {
      i = i + 1;
      outputFile = argv[i];
      out.open(outputFile);
      std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
      std::cout.rdbuf(out.rdbuf()); 
      hasOutputFile = true;
    }
    else if (0 == strncmp(argv[i], "-k", 2) || 0 == strncmp(argv[i], "--key", 5)) {
      i = i + 1;
      key = argv[i];
      hasKey = true;
    }
    else {
      std::cerr << "Unrecognized option." << std::endl;
      std::cerr << usageWarning << std::endl;
      return 1;
    }

  }

  Serpent serpent; 

  unsigned char testKey[] = {0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00};

  unsigned char plaintext[16] = 
   {0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00};

 if (hasKey) {
   unsigned char new_key[32];
   int index = 0;
   for (int i = 0; i < key.length() - 2; i++) {
     std::stringstream ss;
     ss << std::hex << key[i] << key[i+1];
     int n;
     ss >> n;
     unsigned char x = (unsigned char)n;
     new_key[index] = x;
     index += 1;
     i += 1;
   }
   memcpy(testKey, new_key, sizeof(testKey));
 }

 if (hasInputFile) {
    unsigned char new_plaintext[16];

    std::ifstream in(inputFile);
    unsigned char  x;
    int index = 0;

    std::string temp_string = "";

    while (in >> std::noskipws >> x) {

      std::cout << "X: " << std::hex << x << std::endl;
      temp_string += x;

      if (temp_string.length() == 2) {
        std::stringstream ss;
        ss << std::hex << temp_string;
        int n = 0;
        ss >> n;
        unsigned char y = (unsigned char)n;
        new_plaintext[index] = y;
        index += 1;
        temp_string = "";
      }
    }
   // Set plaintext to be theplaintext we read in from file
    memcpy(plaintext, new_plaintext, sizeof(plaintext));  
 }
 else {
 }


  serpent.setKeySize(sizeof(testKey)/sizeof(*testKey));
  serpent.setKey(testKey);
  serpent.generateSubKeys();

  std::cout << "TESTING" << std::endl;
  int encryptionRound = 0;


  while (encryptionRound < nonce) {
    std::cout << std::dec << "================================ ROUND <<
    encryptionRound << " ================================\n" << std::endl;
    serpent.encrypt(plaintext);
    std::cout << std::dec << "============================ END ROUND " << 
    encryptionRound     << " ============================\n"<< std::endl;
    encryptionRound++;

  }


 if (hasOutputFile){
    out.close();
  }


 return 0;

 }

我运行了 Valgrind 并得到了以下输出,但我对 io 业务非常缺乏经验,不知道如何处理这些信息。

==3131== Memcheck, a memory error detector
==3131== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==3131== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==3131== Command: ./SerpentOpt -n 1 -o output.txt
==3131== 
==3131== Invalid read of size 8
==3131==    at 0x4EC7328: std::ostream::flush() (in /usr/lib/x86_64-
linux gnu/libstdc++.so.6.0.16)
==3131==    by 0x4E97F9B: std::ios_base::Init::~Init() (in /usr/lib/x86_64-linux- 
gnu/libstdc++.so.6.0.16)
==3131==    by 0x5385900: __run_exit_handlers (exit.c:78)
==3131==    by 0x5385984: exit (exit.c:100)
==3131==    by 0x536B773: (below main) (libc-start.c:258)
==3131==  Address 0x7fefffd88 is just below the stack ptr.  To suppress, use: --   
workaround-gcc296-bugs=yes
==3131== 
==3131== 
==3131== Process terminating with default action of signal 11 (SIGSEGV)
==3131==  Bad permissions for mapped region at address 0x4224580
==3131==    at 0x4224580: ??? (in /lib/x86_64-linux-gnu/ld-2.15.so)
==3131==    by 0x4EC732D: std::ostream::flush() (in /usr/lib/x86_64-linux-  
gnu/libstdc++.so.6.0.16)
==3131==    by 0x4E97F9B: std::ios_base::Init::~Init() (in /usr/lib/x86_64-linux-   
gnu/libstdc++.so.6.0.16)
==3131==    by 0x5385900: __run_exit_handlers (exit.c:78)
==3131==    by 0x5385984: exit (exit.c:100)
==3131==    by 0x536B773: (below main) (libc-start.c:258)
==3131== 
==3131== HEAP SUMMARY:
==3131==     in use at exit: 0 bytes in 0 blocks
==3131==   total heap usage: 10,745 allocs, 10,745 frees, 493,629 bytes allocated
==3131== 
==3131== All heap blocks were freed -- no leaks are possible
==3131== 
==3131== For counts of detected and suppressed errors, rerun with: -v
==3131== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

感谢所有帮助!

最佳答案

这就是你给自己带来悲伤的地方:

  out.open(outputFile);
  std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
  std::cout.rdbuf(out.rdbuf()); 

现在有两个对象都指向同一个buf。猜猜一个对象被销毁并清理其资源后会发生什么,然后第二个对象开始执行其析构函数。

关于c++ - 与文件 i/o 相关的 c++ 程序末尾的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20382863/

相关文章:

c++ - 指向类变量中函数的指针

c - 是否可以在 linux 中创建一个固定大小的文件?

php - 为什么我在 PHP 中遇到段错误?

C:为什么会出现这个Segmentation Fault?

c++ - 使用前缀或后缀递增(或递减)

c++ - ID3D11Device::CreateBuffer 在幕后做了什么?

c - 如何在C中将多个结果打印到单个文本文件?

Java多线程文件保存

c - 如何在 gdb 中使用输入文件

c++ - 在 Windows 中,如何拥有作为重定向管道的非阻塞标准输入?