Use zone memory for StackTrace::ToCString.
Fixes memory leak of the TextBuffer's buffer. R=fschneider@google.com Review-Url: https://codereview.chromium.org/2689563003 .
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#include "vm/type_table.h"
|
||||
#include "vm/unicode.h"
|
||||
#include "vm/weak_code.h"
|
||||
#include "vm/zone_text_buffer.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
@@ -22332,7 +22333,7 @@ const char* StackTrace::ToCString() const {
|
||||
|
||||
|
||||
static void PrintStackTraceFrame(Zone* zone,
|
||||
TextBuffer* buffer,
|
||||
ZoneTextBuffer* buffer,
|
||||
const Function& function,
|
||||
TokenPosition token_pos,
|
||||
intptr_t frame_index) {
|
||||
@@ -22370,7 +22371,7 @@ const char* StackTrace::ToCStringInternal(intptr_t* frame_index,
|
||||
Code& code = Code::Handle(zone);
|
||||
GrowableArray<const Function*> inlined_functions;
|
||||
GrowableArray<TokenPosition> inlined_token_positions;
|
||||
TextBuffer buffer(1024);
|
||||
ZoneTextBuffer buffer(zone, 1024);
|
||||
|
||||
// Iterate through the stack frames and create C string description
|
||||
// for each frame.
|
||||
@@ -22416,7 +22417,7 @@ const char* StackTrace::ToCStringInternal(intptr_t* frame_index,
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.Steal();
|
||||
return buffer.buffer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -555,5 +555,7 @@
|
||||
'zone.cc',
|
||||
'zone.h',
|
||||
'zone_test.cc',
|
||||
'zone_text_buffer.cc',
|
||||
'zone_text_buffer.h',
|
||||
],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "vm/zone_text_buffer.h"
|
||||
|
||||
#include "platform/assert.h"
|
||||
#include "platform/globals.h"
|
||||
#include "platform/utils.h"
|
||||
#include "vm/os.h"
|
||||
#include "vm/zone.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
ZoneTextBuffer::ZoneTextBuffer(Zone* zone, intptr_t initial_capacity)
|
||||
: zone_(zone), buffer_(NULL), length_(0), capacity_(0) {
|
||||
ASSERT(initial_capacity > 0);
|
||||
buffer_ = reinterpret_cast<char*>(zone->Alloc<char>(initial_capacity));
|
||||
capacity_ = initial_capacity;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ZoneTextBuffer::Printf(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
intptr_t remaining = capacity_ - length_;
|
||||
ASSERT(remaining >= 0);
|
||||
intptr_t len = OS::VSNPrint(buffer_ + length_, remaining, format, args);
|
||||
va_end(args);
|
||||
if (len >= remaining) {
|
||||
EnsureCapacity(len);
|
||||
remaining = capacity_ - length_;
|
||||
ASSERT(remaining > len);
|
||||
va_list args2;
|
||||
va_start(args2, format);
|
||||
intptr_t len2 = OS::VSNPrint(buffer_ + length_, remaining, format, args2);
|
||||
va_end(args2);
|
||||
ASSERT(len == len2);
|
||||
}
|
||||
length_ += len;
|
||||
buffer_[length_] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void ZoneTextBuffer::AddString(const char* s) {
|
||||
Printf("%s", s);
|
||||
}
|
||||
|
||||
|
||||
void ZoneTextBuffer::EnsureCapacity(intptr_t len) {
|
||||
intptr_t remaining = capacity_ - length_;
|
||||
if (remaining <= len) {
|
||||
const int kBufferSpareCapacity = 64; // Somewhat arbitrary.
|
||||
// TODO(turnidge): do we need to guard against overflow or other
|
||||
// security issues here? Text buffers are used by the debugger
|
||||
// to send user-controlled data (e.g. values of string variables) to
|
||||
// the debugger front-end.
|
||||
intptr_t new_capacity = capacity_ + len + kBufferSpareCapacity;
|
||||
buffer_ = zone_->Realloc<char>(buffer_, capacity_, new_capacity);
|
||||
capacity_ = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RUNTIME_VM_ZONE_TEXT_BUFFER_H_
|
||||
#define RUNTIME_VM_ZONE_TEXT_BUFFER_H_
|
||||
|
||||
#include "vm/allocation.h"
|
||||
#include "vm/globals.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
class Zone;
|
||||
|
||||
// TextBuffer maintains a dynamic character buffer with a printf-style way to
|
||||
// append text.
|
||||
class ZoneTextBuffer : ValueObject {
|
||||
public:
|
||||
ZoneTextBuffer(Zone* zone, intptr_t initial_capacity);
|
||||
~ZoneTextBuffer() {}
|
||||
|
||||
intptr_t Printf(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
void AddString(const char* s);
|
||||
|
||||
char* buffer() { return buffer_; }
|
||||
intptr_t length() { return length_; }
|
||||
|
||||
private:
|
||||
void EnsureCapacity(intptr_t len);
|
||||
Zone* zone_;
|
||||
char* buffer_;
|
||||
intptr_t length_;
|
||||
intptr_t capacity_;
|
||||
};
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // RUNTIME_VM_ZONE_TEXT_BUFFER_H_
|
||||
Reference in New Issue
Block a user