Lib
QOLを高める
exceptions.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 #include "include/exceptions.h"
3 #include "include/util.h"
4 #include <psapi.h>
5 #include <sstream>
6 #include <iomanip>
7 
8 namespace yappy {
9 namespace error {
10 
11 std::string createStackTraceMsg(const std::string &msg)
12 {
13  std::string result = msg;
14  result += '\n';
15 
16  // Max count of stack trace
17  const DWORD MaxStackTrace = 62;
18  // Capture current back trace
19  void *stackTrace[MaxStackTrace];
20  USHORT numStackTrace = ::CaptureStackBackTrace(0, 62, stackTrace, nullptr);
21 
22  // Get module list of the current process
23  BOOL bret = FALSE;
24  HANDLE hProc = ::GetCurrentProcess();
25  DWORD neededSize = 0;
26  bret = ::EnumProcessModules(hProc, nullptr, 0, &neededSize);
27  if (!bret) {
28  return std::string("<???>");
29  }
30  DWORD modCount = neededSize / sizeof(HMODULE);
31  std::vector<HMODULE> hMods(modCount);
32  bret = ::EnumProcessModules(hProc, hMods.data(), neededSize, &neededSize);
33  if (!bret) {
34  return std::string("<???>");
35  }
36  hMods.resize(neededSize / sizeof(HMODULE));
37 
38  // Sort modules by load address
39  auto hmoduleComp = [](HMODULE a, HMODULE b) {
40  return reinterpret_cast<uintptr_t>(a) < reinterpret_cast<uintptr_t>(b);
41  };
42  std::sort(hMods.begin(), hMods.end(), hmoduleComp);
43 
44  // Get module name list
45  std::vector<std::string> modNames;
46  modNames.reserve(hMods.size());
47  for (DWORD i = 0; i < modCount; i++) {
48  char baseName[256];
49  DWORD ret = ::GetModuleBaseNameA(hProc, hMods[i], baseName, sizeof(baseName));
50  if (ret == 0) {
51  ::strcpy_s(baseName, "???");
52  }
53  modNames.emplace_back(baseName);
54  }
55 
56  // Create string
57  // [address] +diff [module base]
58  for (uint32_t i = 0; i < numStackTrace; i++) {
59  char str[32];
60  sprintf_s(str, "%p", stackTrace[i]);
61  result += str;
62  result += ' ';
63 
64  // Binary search trace_element[i] from module list
65  auto it = std::upper_bound(hMods.begin(), hMods.end(),
66  (HMODULE)stackTrace[i], hmoduleComp);
67  size_t ind = std::distance(hMods.begin(), it);
68  if (ind > 0) {
69  uintptr_t diff = reinterpret_cast<uintptr_t>(stackTrace[i])
70  - reinterpret_cast<uintptr_t>(hMods.at(ind - 1));
71  sprintf_s(str, "%p", reinterpret_cast<void *>(diff));
72  result += '+';
73  result += str;
74  result += ' ';
75  result += modNames.at(ind - 1);
76  }
77  else {
78  result += "???";
79  }
80  result += "\n";
81  }
82 
83  return result;
84 }
85 
86 
87 Win32Error::Win32Error(const std::string &msg, DWORD code) :
88  runtime_error("")
89 {
90  char *lpMsgBuf = NULL;
91  DWORD ret = ::FormatMessageA(
92  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
93  nullptr, code, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
94  reinterpret_cast<LPSTR>(&lpMsgBuf), 0, nullptr);
95  auto del = [](char *p) {
96  ::LocalFree(p);
97  };
98  std::unique_ptr<char, decltype(del)> pMsgBuf(lpMsgBuf, del);
99  const char *info = (ret != 0) ? lpMsgBuf : "<FormatMessageA failed>";
100 
101  // "msg (0x????????: errdesc)"
102  std::stringstream ss;
103  ss << msg << " (0x";
104  ss << std::hex << std::setw(8) << std::setfill('0') << code;
105  ss << ": " << info << ")";
106  m_what = ss.str();
107 }
108 
109 const char *Win32Error::what() const
110 {
111  return m_what.c_str();
112 }
113 
114 MmioError::MmioError(const std::string &msg, UINT code) :
115  runtime_error("")
116 {
117  std::stringstream ss;
118  ss << msg << " (" << code << ")";
119  m_what = ss.str();
120 }
121 
122 const char *MmioError::what() const
123 {
124  return m_what.c_str();
125 }
126 
127 OggVorbisError::OggVorbisError(const std::string &msg, int code) :
128  runtime_error("")
129 {
130  // signed decimal
131  std::stringstream ss;
132  ss << msg << " (" << code << ")";
133  m_what = ss.str();
134 }
135 
136 const char *OggVorbisError::what() const
137 {
138  return m_what.c_str();
139 }
140 
141 DXError::DXError(const std::string &msg, HRESULT hr) :
142  runtime_error("")
143 {
144  // "msg (0x????????)"
145  std::stringstream ss;
146  ss << msg << " (0x";
147  ss << std::hex << std::setw(8) << std::setfill('0') << hr;
148  ss << ")";
149  m_what = ss.str();
150 }
151 
152 const char *DXError::what() const
153 {
154  return m_what.c_str();
155 }
156 
157 } // namespace error
158 } // namespace yappy
const char * what() const override
Definition: exceptions.cpp:152
const char * str
Definition: input.cpp:197
const char * what() const override
Definition: exceptions.cpp:136
OggVorbisError(const std::string &msg, int code)
Definition: exceptions.cpp:127
std::string createStackTraceMsg(const std::string &msg)
Returns (msg + stacktrace) string.
Definition: exceptions.cpp:11
Definition: config.cpp:6
DXError(const std::string &msg, HRESULT hr)
Definition: exceptions.cpp:141
Utilities.
Win32Error(const std::string &msg, DWORD code)
Definition: exceptions.cpp:87
const char * what() const override
Definition: exceptions.cpp:122
char msg[LINE_DATA_SIZE-sizeof(LARGE_INTEGER)-sizeof(uint32_t)]
Definition: debug.cpp:159
MmioError(const std::string &msg, UINT code)
Definition: exceptions.cpp:114
const char * what() const override
Definition: exceptions.cpp:109