【问题标题】:Embarrassing error when reading string literal into a pointer将字符串文字读入指针时出现令人尴尬的错误
【发布时间】:2013-03-07 02:07:35
【问题描述】:

我觉得这个帖子有点迟钝,但我不知道为什么我的程序在从键盘读取字符串文字时会爆炸(即,然后将其分配给指针)。

调试了一个多小时,程序从键盘读取时一直在爆炸。

我已尽一切努力解决此问题。将字符串初始化为字符串文字(即编译器说它有 nullptr 问题)。这几乎就像我在某个地方有一个看不见的角色。如果有人能告诉我我做错了什么,我将不胜感激。

ma​​in.cpp

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>

#include <iostream>
#include <fstream>
#include "protocol.h"

int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

int menuChoice = 0;

char * fileName = nullptr;
char * byteArray = nullptr;
char * hexArray = nullptr;
int numberOfBytes = 0;

PrintMenu();
GetMenuChoice(menuChoice);
ExecuteMenuChoice(menuChoice, fileName, byteArray, hexArray, numberOfBytes);

return 0;
}

protocol.cpp

void GetFile(char * fileName)
{

//Prompt user for binary file
std::cout << "\nEnter filename: " << std::endl;

//Read in location of binary file
std::cin.ignore(std::cin.rdbuf()->in_avail());
std::cin.getline(fileName, 256);
std::cin.clear();
std::cin.ignore(std::cin.rdbuf()->in_avail());
}

protocol.h

#ifndef PROTOCOL_H
#define PROTOCOL_H

//Function declarations
void PrintMenu();
void GetMenuChoice(int &menuChoice);
void ExecuteMenuChoice(int menuChoice, char *& fileName, char *& byteArray,
                   char *& hexArray, int numberOfBytes);
void NewLine();
void ThankUser();
void ErrorMessage();

#endif

【问题讨论】:

  • 它不是字符串文字,除非它是源代码中存在的字符串。
  • 我马上怀疑std::cin.getline(fileName, 256);。但是你甚至没有展示它是如何被使用的。重现问题的最小示例在哪里?
  • “程序不断炸”是什么意思?
  • 丢失char *fileName(就此而言所有此代码中的char *s)并改用std::string
  • 我同意,这个问题会比较尴尬……

标签: c++ pointers hexdump


【解决方案1】:

您发布的代码不完整,但我没有看到您在调用 std::cin.getline(fileName, 256) 之前分配文件名。

【讨论】:

    【解决方案2】:

    我没有看到您在任何地方调用 GetFile,但它看起来需要分配的缓冲区或字符数组。在main() 中,您声明了char *fileName,但不为其分配任何内存。如果您致电(来自main()GetFile(fileName),那么我预计它会崩溃。您需要在main()GetFile() 中分配空间来读取数据。

    【讨论】:

      【解决方案3】:

      传递要填充的字符串文字没有任何意义。你需要传递一个缓冲区:

      #include <iostream>
      #include <fstream>
      #include <stdlib.h> // for _MAX_PATH
      
      int main()
      {
          char filename[_MAX_PATH];
      
          GetFile(filename);
      
          std::cout << filename << std::endl;
      }
      

      _MAX_PATH 比硬编码像256 这样的任意值更有意义。

      最好还是使用std::string 并完全删除这些缓冲区大小!

      #include <iostream>
      
      void GetFile(std::string& fileName)
      {
          std::cout << "\nEnter filename: " << std::endl;
      
          std::getline(std::cin, fileName);
      }
      
      int main()
      {
          std::string filename;
      
          GetFile(filename);
      
          std::cout << filename << std::endl;
      }
      

      【讨论】:

      【解决方案4】:

      cin::getline() 不会为您分配内存来将字符串文字存储到fileName 中。你必须为它提供内存空间,通过分配内存给fileName,就像

      fileName = new char[_MAX_PATH];
      

      最后别忘了释放内存

      delete[] fileName;
      

      【讨论】:

      • malloc()free()?这个问题不是标记c++吗?
      • c++ 不拒绝malloc & free,它是多范式的。但是,new & free 应该是更好的选择:-)
      • 不拒绝这些函数并不意味着它们是惯用的 C++。使用您编辑的new 更接近C++ 风格,但这需要与delete [] 结合使用。由于您在编译时知道大小,因此按照我的回答在堆栈上分配内存会更有意义。
      • 谢谢 :-) 我更喜欢在实践中使用std::string,而不是在堆栈上分配内存,尽管大小在编译时是已知的。我喜欢保持小堆栈,尽可能避免潜在的堆栈溢出。
      猜你喜欢
      • 2018-11-24
      • 1970-01-01
      • 2018-03-19
      • 2017-08-01
      • 1970-01-01
      • 2021-11-21
      • 2016-07-23
      • 2018-10-27
      • 2020-03-29
      相关资源
      最近更新 更多