I am learning Rust by writing simple binary decoder.
I'm using a BufferedReader with the byteorder crate to read numbers, but I'm having problems with reading byte buffers.
I want to read byte data into buffer allocated at runtime.
Then I want to pass ownership of this buffer to a struct. When struct is no longer in use, the buffer should be deallocated.
There seems to be no way to allocate array with size determined at runtime on heap except some Vec::with_capacity() hacks. Any ideas how to implement this with proper Rust semantics?
This will create a pre-allocated mutable 500MB byte buffer of zeros stored on the heap with no need for unsafe rust:
// Correct
let mut buffer = vec![0_u8; 536870912];
Note that the following code below is not a good idea and will most likely result in a stack overflow because the buffer is created on the stack before being boxed and moved to the heap.
// Incorrect - stack used
let mut bytes: Box<[u8]> = Box::new([0_u8; 536870912])
// Incorrect - slow
let mut bytes = Vec::with_capacity(536870912);
for _ in 0..bytes.capacity() {
bytes.push(0_u8);
}
Rust is a low-level language; thus you can allocate raw memory and then fill it with objects yourself. Of course, it will require unsafe code, as all fiddling with raw memory does.
Here is a complete example:
use std::{
alloc::{self, Layout},
mem, ptr,
};
fn main() {
unsafe {
let layout = Layout::from_size_align(512 * 1024, 4 * 1024).expect("Invalid layout");
let mut raw: *mut i32 = mem::transmute(alloc::alloc(layout));
for i in 0..(512 * 1024 / 4) {
ptr::write(raw, i as i32);
raw = raw.offset(1)
}
}
}
Of course, in real code, I would just use Vec to safely manage the memory for me. It's just simpler!
I tried using box but it seems that it is experimental and I can't use it with release branch. Any ideas how to implement this with proper Rust semantics?
This is covered in The Rust Programming Language, specifically the section "Using Box<T> to Point to Data on the Heap".
Use Box::new:
fn main() {
let answer: Box<u8> = Box::new(42);
}
See also:
Allocate array onto heap with size known at runtime
Is there any way to allocate a standard Rust array directly on the heap, skipping the stack entirely?
How to allocate arrays on the heap in Rust 1.0?
Creating a fixed-size array on heap in Rust
How do I allocate an array at runtime in Rust?
Thread '<main>' has overflowed its stack when allocating a large array using Box
Related
This issue is my misunderstanding of how the standard is using my custom allocator. I have a stateful allocator that keeps a vector of allocated blocks. This vector is pushed into when allocating and searched through during de-allocation.
From my debugging it appears that different instances of my object (this*'s differ) are being called on de-allocation. An example may be that MyAllocator (this* = 1) is called to allocate 20 bytes, then some time later MyAllocator (this* = 2) is called to de-allocate the 20 bytes allocated earlier. Abviously the vector in MyAllocator (this* = 2) doesn't contain the 20 byte block allocated by the other allocator so it fails to de-allocate. My understanding was that C++11 allows stateful allocators, what's going on and how do i fix this?
I already have my operator == set to only return true when this == &rhs
pseudo-code:
template<typename T>
class MyAllocator
{
ptr allocate(int n)
{
...make a block of size sizeof(T) * n
blocks.push_back(block);
return (ptr)block.start;
}
deallocate(ptr start, int n)
{
/*This fails because the the block array is not the
same and so doesn't find the block it wants*/
std::erase(std::remove_if(blocks.begin,blocks.end, []()
{
return block.start >= (uint64_t)ptr && block.end <= ((uint64_t)ptr + sizeof(T)*n);
}), blocks.end);
}
bool operator==(const MyAllocator& rhs)
{
//my attempt to make sure internal states are same
return this == &rhs;
}
private:
std::vector<MemoryBlocks> blocks;
}
Im using this allocator for an std::vector, on gcc. So as far as i know no weird rebind stuff is going on
As #Igor mentioned, allocators must be copyable. Importantly though they must share their state between copies, even AFTER they have been copied from. In this case the fix was easy, i made the blocks vector a shared_ptr as suggested and then now on copy all the updates to that vector occur to the same vector, since they all point to the same thing.
Suppose I have the following struct –
struct MyStruct {
var value1: UInt16
var value2: UInt16
}
And I use this struct somewhere in my code like so -
var s = MyStruct(value1: UInt16(0), value2: UInt16(0))
I know that the struct will require 32-bits of storage for the two 16-bit integers –
What I am not certain about is whether swift is allocating two additional 64-bit pointers for each value in addition to one 64-bit pointer for the variable s.
Does this mean total storage requirement for the above code would result in the following?
MyStruct.value1 - 16-bits
MyStruct.value1 ptr - 64-bits
MyStruct.value2 - 16-bits
MyStruct.value2 ptr - 64-bits
s ptr - 64-bits
–––––––––––––––––––––––––––––
Total - 224-bits
Can someone please clarify?
MyStruct is 4 bytes because sizeof(UInt16) is 2 bytes. To test this for any given type, use sizeof. sizeof return the memory in bytes.
let size = sizeof(MyStruct) //4
If you want to get the size of a given instance you can use sizeOfValue.
var s = MyStruct(value1: UInt16(0), value2: UInt16(0))
let sSize = sizeofValue(s) //4
I believe the size of the pointer will depend on the architecture/compiler which is 64-bits on most computers and many newer phones but older ones might be 32 bit.
I don't think there is a way to actually get a pointer to MyStruct.value1, correct me if i'm wrong (i'm trying &s.value1.
Pointers
Structs in Swift are created and passed around on the stack, that's why they have value semantics instead of reference semantics.
When a struct is created in a function, it is stored on the stack so it's memory is freed up at the end of the function. It's reference is just an offset from the Stack Pointer or Frame Pointer.
It'll be four bytes on the stack.
Just try it in a XCode Playground:
The answer is 4 bytes.
I would like to create a memory manager/allocator which allocates memory with any specified size.
I have tried using Boost and ACE memory allocator but they allocates only specif type of data
In ACE_cached_allocator if allocator is int type we can only allocate memory for int, cant get for char.
example:- i can ask any size of memory like int, char or any class/structure
please suggest any lib for such application
I think you just want malloc. You can allocate memory for an array of 20 int like this:
int *a = (int *)malloc(sizeof *a * 20);
a[0] = 1234;
a[1] = 4567;
free(a);
If you have a structure or class with type Foo it's just:
Foo *fp = (Foo *)malloc(sizeof *fp);
The answer seems simple, so did I misunderstand your question?
(Note: the casts aren't necessary in C.)
I have a linked list structure like this
typedef struct list_node {
int data;
struct list_node *next;
}l_node;
void print_list(l_node *head) {
l_node *cur_node = head;
while(cur_node!=NULL) {
printf("%d\t", cur_node->data);
cur_node = cur_node->next;
}
}
void main() {
printf("List");
l_node *new_node = (l_node*)malloc(sizeof(l_node));
print_list(new_node);
}
When I compile gcc linkedlist.c and do ./a.out
I get output
List
0
But when I tried it in VC++, I got error (since I am trying to access invalid memory location in cur_node->next).
So, does malloc of gcc allocate 0 value by default to the integer variable inside the structure? Why I didn't get the same error while doing the same print_list in gcc?
The contents of the memory returned by malloc are not initialized. You cannot read from that memory before you initialize it (by writing to it at least once).
gcc may be "helpfully" zero-initializing the memory, but that behavior isn't required. The Visual C++ C Runtime (CRT) will give you uninitialized memory in a release build (for maximum performance) and memory initialized with the special fill byte 0xcd in a debug build (to help you find where you may be using uninitialized memory).
So, basically, you need to initialize the memory before you use it. If you want the runtime to zero-initialize the heap block before it gives it to you, you may use calloc.
you need to assign new_node->next = NULL because you check if the current node is NULL or not, and malloc does not initialize the allocated space with any value, so there is no gurantee that the value would be initialized. To be safe you need to assign NULL manually to the tail of the linked list, or an invalid pointer.
Visual C++ debug runtime library features so-called allocation hooks. Works this way: you define a callback and call _CrtSetAllocHook() to set that callback. Now every time a memory allocation/deallocation/reallocation is done CRT calls that callback and passes a handful of parameters.
I successfully used an allocation hook to find a reproduceable memory leak - basically CRT reported that there was an unfreed block with allocation number N (N was the same on every program run) at program termination and so I wrote the following in my hook:
int MyAllocHook( int allocType, void* userData, size_t size, int blockType,
long requestNumber, const unsigned char* filename, int lineNumber)
{
if( requestNumber == TheNumberReported ) {
Sleep( 0 );// a line to put breakpoint on
}
return TRUE;
}
since the leak was reported with the very same allocation number every time I could just put a breakpoint inside the if-statement and wait until it was hit and then inspect the call stack.
What other useful things can I do using allocation hooks?
You could also use it to find unreproducible memory leaks:
Make a data structure where you map the allocated pointer to additional information
In the allocation hook you could query the current call stack (StackWalk function) and store the call stack in the data structure
In the de-allocation hook, remove the call stack information for that allocation
At the end of your application, loop over the data structure and report all call stacks. These are the places where memory was allocated but not freed.
The value "requestNumber" is not passed on to the function when deallocating (MS VS 2008). Without this number you cannot keep track of your allocation. However, you can peek into the heap header and extract that value from there:
Note: This is compiler dependent and may change without notice/ warning by the compiler.
// This struct is a copy of the heap header used by MS VS 2008.
// This information is prepending each allocated memory object in debug mode.
struct MsVS_CrtMemBlockHeader {
MsVS_CrtMemBlockHeader * _next;
MsVS_CrtMemBlockHeader * _prev;
char * _szFilename;
int _nLine;
int _nDataSize;
int _nBlockUse;
long _lRequest;
char _gap[4];
};
int MyAllocHook(..) { // same as in question
if(nAllocType == _HOOK_FREE) {
// requestNumber isn't passed on to the Hook on free.
// However in the heap header this value is stored.
size_t headerSize = sizeof(MsVS_CrtMemBlockHeader);
MsVS_CrtMemBlockHeader* pHead;
size_t ptr = (size_t) pvData - headerSize;
pHead = (MsVS_CrtMemBlockHeader*) (ptr);
long requestNumber = pHead->_lRequest;
// Do what you like to keep track of this allocation.
}
}
You could keep record of every allocation request then remove it once the deallocation is invoked, for instance: This could help you tracking memory leak problems that are way much worse than this to track down.
Just the first idea that comes to my mind...