【问题标题】:Can I check if memory block is readable without raising exception with C++?我可以在不使用 C++ 引发异常的情况下检查内存块是否可读吗?
【发布时间】:2013-08-23 04:20:54
【问题描述】:

对于 C++ 代码中的异常处理程序,我需要以下内容。说,我有以下代码块:

void myFunction(LPCTSTR pStr, int ncbNumCharsInStr)
{
    __try
    {
        //Do work with 'pStr'

    }
    __except(1)
    {
        //Catch all

        //But here I need to log `pStr` into event log
        //For that I don't want to raise another exception
        //if memory block of size `ncbNumCharsInStr` * sizeof(TCHAR)
        //pointed by 'pStr' is unreadable.
        if(memory_readable(pStr, ncbNumCharsInStr * sizeof(TCHAR)))
        {
            Log(L"Failed processing: %s", pStr);
        }
        else
        {
            Log(L"String at 0x%X, %d chars long is unreadable!", pStr, ncbNumCharsInStr);
        }
    }
}

有没有办法实现memory_readable

【问题讨论】:

  • IsBadReadPtr() 不适合你吗?
  • 根据该页面的文档,结构化异常处理是可行的方法,除非我解释不正确。我从来没有这样做过,所以我可能是。
  • 在您尝试执行此操作之前,请先阅读这篇文章:blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx
  • @Naveen,MSDN 文章需要在适当的地方链接到 Raymond Chen 的帖子:p
  • @c00000fd:不正确的程序不值得运行。

标签: c++ windows winapi memory-management


【解决方案1】:

VirtualQuery 函数可能会有所帮助。以下是如何使用它实现memory_readable 的快速说明。

bool memory_readable(void *ptr, size_t byteCount)
{
  MEMORY_BASIC_INFORMATION mbi;
  if (VirtualQuery(ptr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
    return false;

  if (mbi.State != MEM_COMMIT)
    return false;

  if (mbi.Protect == PAGE_NOACCESS || mbi.Protect == PAGE_EXECUTE)
    return false;

  // This checks that the start of memory block is in the same "region" as the
  // end. If it isn't you "simplify" the problem into checking that the rest of 
  // the memory is readable.
  size_t blockOffset = (size_t)((char *)ptr - (char *)mbi.AllocationBase);
  size_t blockBytesPostPtr = mbi.RegionSize - blockOffset;

  if (blockBytesPostPtr < byteCount)
    return memory_readable((char *)ptr + blockBytesPostPtr,
                           byteCount - blockBytesPostPtr);

  return true;
}

注意:我的背景是 C,所以虽然我怀疑有比在 C++ 中转换为 char * 更好的选择,但我不确定它们是什么。

【讨论】:

  • 有趣。谢谢。 TCHAR 只是 wchar_t 或 2 字节字符。我希望我更多地了解内存映射,看看它是如何工作的。也许其他人可以分析它?
【解决方案2】:

您可以使用ReadProcessMemory 函数。如果函数返回0,则地址不可读,否则可读。

返回值

如果函数失败,返回值为 0(零)。得到扩展 错误信息,请致电GetLastError

如果请求的读操作跨越到一个 进程中不可访问的区域。

如果函数成功,返回值非零。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-06
    • 2016-10-12
    • 2019-03-23
    • 1970-01-01
    • 2010-11-29
    • 2022-11-24
    • 2020-03-26
    相关资源
    最近更新 更多