C++ 调用ReadFile后,程序在debug_heap.cpp中命中断点

C++ 调用ReadFile后,程序在debug_heap.cpp中命中断点,c++,winapi,C++,Winapi,这个函数应该从文件中读取字符串并返回它,但在调用ReadFile程序后,立即在第985行的debug_heap.cpp文件中点击断点 char* readFile() { char curDirectory[MAX_PATH]; GetCurrentDirectory(MAX_PATH, curDirectory); char filePath[MAX_PATH]; char *name = "\\data.txt"; sprintf_s(filePath, "%s%s", curDire

这个函数应该从文件中读取字符串并返回它,但在调用ReadFile程序后,立即在第985行的debug_heap.cpp文件中点击断点

char* readFile()
{
char curDirectory[MAX_PATH];
GetCurrentDirectory(MAX_PATH, curDirectory);

char filePath[MAX_PATH];

char *name = "\\data.txt";

sprintf_s(filePath, "%s%s", curDirectory, name);

HANDLE hFile = CreateFile(filePath, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (hFile == INVALID_HANDLE_VALUE)
{
    DisplayError("Can't Create File");
    return NULL;
}

DWORD fileSize = GetFileSize(hFile, NULL);

char *buffer = new char[fileSize / 2 + 1];
DWORD bytesReaded;

if (ReadFile(hFile, buffer, fileSize, &bytesReaded, NULL) == 0)
{
    DisplayError("Can't read File");
    return NULL;
}

buffer[bytesReaded] = '\0';

CloseHandle(hFile);

return buffer;
}

这是因为您的代码写入的内容超出了缓冲区的末尾。您可以这样分配
缓冲区

char *buffer = new char[fileSize / 2 + 1];
但随后您尝试从文件中读取
文件大小
字节。您的分配应改为:

char *buffer = new char[fileSize + 1];
其他一些评论:

  • 调用
    sprintf\u s
    可能会导致缓冲区溢出 由于C++中的代码,请使用<代码> STD::String < /C> >并使该类管理缓冲区。对于
    文件路径
    缓冲区
    ,都应该这样做。这将允许您避免当前代码的泄漏。例如,故障在
    ReadFile
    泄漏内存后返回。而且它避免了调用代码释放内存的负担
  • 如果代码在
    ReadFile
    之后接受失败返回,则也会泄漏文件句柄
  • bytesRead
    应命名为
    bytesRead
    ,以使用正确的英语单词
  • 没有真正的理由相信可执行文件位于当前工作目录中
      这是因为您的代码写入的内容超出了缓冲区的末尾。您可以这样分配
      缓冲区

      char *buffer = new char[fileSize / 2 + 1];
      
      但随后您尝试从文件中读取
      文件大小
      字节。您的分配应改为:

      char *buffer = new char[fileSize + 1];
      
      其他一些评论:

      • 调用
        sprintf\u s
        可能会导致缓冲区溢出 由于C++中的代码,请使用<代码> STD::String < /C> >并使该类管理缓冲区。对于
        文件路径
        缓冲区
        ,都应该这样做。这将允许您避免当前代码的泄漏。例如,故障在
        ReadFile
        泄漏内存后返回。而且它避免了调用代码释放内存的负担
      • 如果代码在
        ReadFile
        之后接受失败返回,则也会泄漏文件句柄
      • bytesRead
        应命名为
        bytesRead
        ,以使用正确的英语单词
      • 没有真正的理由相信可执行文件位于当前工作目录中
      你试着读
      文件大小
      但你只分配
      新字符[fileSize/2+1]
      你试着读
      文件大小
      但你只分配
      新字符[fileSize/2+1]
      关于最后一个要点,我在你的最后一个问题上告诉过你,但可能没有理解。当前目录并不总是可执行文件所在的目录。通常它是一个不同的目录。他也在泄漏句柄,最好用一个类或自定义删除器的唯一指针包装这些句柄。我是如何泄漏句柄的?文件句柄在函数末尾关闭。请参阅,这就是发明析构函数的原因。因为人们在C中泄漏,他们不知道为什么。如果
      ReadFile
      失败会发生什么?如果在
      ReadFile
      之后执行失败返回,则会泄漏内存和文件句柄。关于最后一个要点,我在你的最后一个问题中告诉过你,但可能没有理解。当前目录并不总是可执行文件所在的目录。通常它是一个不同的目录。他也在泄漏句柄,最好用一个类或自定义删除器的唯一指针包装这些句柄。我是如何泄漏句柄的?文件句柄在函数末尾关闭。请参阅,这就是发明析构函数的原因。因为人们在C中泄漏,他们不知道为什么。如果
      ReadFile
      失败会发生什么情况?如果在
      ReadFile
      之后执行失败返回,则会泄漏内存和文件句柄。