Index: base/process/process_metrics_win.cc |
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc |
index fe4b84988f1a2736da6fef1b9a3c5ca0552f5ba0..e1a5bfecad99431f46038ba797fe54ec405e0454 100644 |
--- a/base/process/process_metrics_win.cc |
+++ b/base/process/process_metrics_win.cc |
@@ -11,6 +11,7 @@ |
#include <winternl.h> |
#include <algorithm> |
+#include <memory> |
#include "base/logging.h" |
#include "base/memory/ptr_util.h" |
@@ -148,41 +149,43 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { |
DCHECK(ws_usage); |
memset(ws_usage, 0, sizeof(*ws_usage)); |
- DWORD number_of_entries = 4096; // Just a guess. |
- PSAPI_WORKING_SET_INFORMATION* buffer = NULL; |
+ // Call QueryWorkingSet once to get number of items. |
+ PSAPI_WORKING_SET_INFORMATION initial_buffer; |
+ QueryWorkingSet(process_, &initial_buffer, sizeof(initial_buffer)); |
+ if (GetLastError() != ERROR_BAD_LENGTH) |
+ return false; |
+ |
+ DWORD number_of_entries = static_cast<DWORD>(initial_buffer.NumberOfEntries); |
+ |
+ std::unique_ptr<PSAPI_WORKING_SET_INFORMATION> buffer; |
int retries = 5; |
for (;;) { |
+ // Maybe some entries are being added right now. Increase the buffer to |
+ // take that into account. |
+ number_of_entries = static_cast<DWORD>(number_of_entries * 1.1); |
+ |
DWORD buffer_size = sizeof(PSAPI_WORKING_SET_INFORMATION) + |
(number_of_entries * sizeof(PSAPI_WORKING_SET_BLOCK)); |
- // if we can't expand the buffer, don't leak the previous |
- // contents or pass a NULL pointer to QueryWorkingSet |
- PSAPI_WORKING_SET_INFORMATION* new_buffer = |
- reinterpret_cast<PSAPI_WORKING_SET_INFORMATION*>( |
- realloc(buffer, buffer_size)); |
- if (!new_buffer) { |
- free(buffer); |
- return false; |
- } |
- buffer = new_buffer; |
+ // Allocate the buffer. |
+ DCHECK(!buffer.get()); |
+ buffer.reset(reinterpret_cast<PSAPI_WORKING_SET_INFORMATION*>( |
+ new uint8_t[buffer_size])); |
brucedawson
2016/09/07 00:41:12
This seems slightly dodgy, using unique_ptr to hol
|
// Call the function once to get number of items |
- if (QueryWorkingSet(process_, buffer, buffer_size)) |
+ if (QueryWorkingSet(process_, buffer.get(), buffer_size)) |
break; // Success |
- if (GetLastError() != ERROR_BAD_LENGTH) { |
- free(buffer); |
+ if (GetLastError() != ERROR_BAD_LENGTH) |
return false; |
- } |
+ // Need to grow the number of entries. |
number_of_entries = static_cast<DWORD>(buffer->NumberOfEntries); |
- |
- // Maybe some entries are being added right now. Increase the buffer to |
- // take that into account. |
- number_of_entries = static_cast<DWORD>(number_of_entries * 1.25); |
+ // Free the current buffer before allocating one with larger size. |
+ buffer.reset(); |
if (--retries == 0) { |
- free(buffer); // If we're looping, eventually fail. |
+ // If we're looping, eventually fail. |
return false; |
} |
} |
@@ -205,7 +208,6 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { |
ws_usage->priv = ws_private * PAGESIZE_KB; |
ws_usage->shareable = ws_shareable * PAGESIZE_KB; |
ws_usage->shared = ws_shared * PAGESIZE_KB; |
- free(buffer); |
return true; |
} |