I am allocating the memory with GetMem (1028 bytes length), so I have an allocated Pointer.
Then I am reading the content and I know that there is e.g. 1028 bytes read.
how can I cast pointer, or convert it to a string?
Should I null terminate the content of the memory prior to conversion?
Thanks!
Use SetString. Pass it a string variable, your pointer, and the string length (1028). Delphi strings are implicitly null-terminated, so the function will add that automatically (even if your buffer already has null bytes in it).
Better yet, set the length of the string and read your data directly into it instead of using an intermediary buffer. If you must use an intermediary buffer, you may as well use one that's statically sized to 1028 bytes instead of complicating your program with dynamic memory management.
Related
I need to allocate a buffer of ASCII characters of fixed length because I receive a (index,7-char chunk) tuples in random order from a distant device.
In C/C++ I would do:
char buffer[3*7+1];
memcpy(&buffer[indexOfTheChunk*7],incomingChunk,7);
How should I proceed in dart?
You can create a fixed-size buffer by making a non-growable List:
var buffer = List<int>.filled(elementCount);
Dart also provides a Uint8List class specifically for creating fixed-size buffers of 8-bit bytes.
If you need to extract a Dart String from the ASCII bytes later, you can call ascii.decode on the List<int>/Uint8List.
I have some files written on an Android device, it wrote bytes in big endian.
Now i try to read this file with iOS and there i need them in small endian.
I can make a for loop and
int temp;
for(...) {
[readFile getBytes:&temp range:NSMakeRange(offset, sizeof(int))];
target_array[i] = CFSwapInt32BigToHost(temp);
// read more like that
}
However it feels silly to read every single value and turn it before i can store it. Can i tell the NSData that i want the value read with a certain byte-order so that i can directly store it where it should be ?
(and save some time, as the data can be quite large)
I also worry about errors when some datatype changes and i forget to use the 16 instead of the 32 swap.
No, you need to swap every value. NSData is just a series of bytes with no value or meaning. It is your app that understands the meaning so it is your code logic that must swap each set of bytes as needed.
The data could be filled with all kinds of values of different sizes. 8-bit values, 16-bit values, 32-bit values, etc. as well as string data or just a stream of bytes that don't need any ordering at all. And the NSData can contain any combination of these values.
Given all of this, there is no simple way to tell NSData that the bytes need to be treated in a specific endianness.
If your data is, for example, nothing but 32-bit integer values stored in a specific endianness and you want to extract an array of bytes, create a helper class that does the conversion.
I am fairly new to programming and am starting to learn the ins and outs of memory allocation. One question that recently occurred to me that I haven't yet been able to find a clear answer to is do memory addresses themselves take up memory. For example, in a 32-bit system, the way I understand it is that each address in 4 bytes and they will typically refer to an empty 'bucket' in memory that is capable of storing 1 byte of data. Does this mean that for each memory location in a 32-bit system, we are actually using 5 bytes of memory(meaning 4 for the address and 1 for the empty bucket)? I'm sure I am missing something here but any clarification would be much appreciated. Thanks!
To reference a memory address you need to express that memory address somehow, and on 32 bit system a memory reference takes 4 bytes indeed. So for any addressable memory address, somewhere else in memory there are 4 bytes that have that address.
But this does not cascade to an x5 multiplication, because a program does not need to reference every byte of memory. It only needs the address where something in memory starts, and then it can work its way to every byte of that 'something' using arithmetic.
To give an example: you have a string in memory Justin Foss. Is it at address 0x10000000, and this address is stored in a variable. So the actual variable value is 0x10000000, pointing to the string Justin Foss. But at 0x10000000 you only have one byte, the J. At 0x10000001 there is the u, at 0x10000002 is the s and so on. Your application does not need a variable for each character, it only needs one variable (4 bytes) to the beginning of the string. Same for object (fields): you only store the address where the objects starts, and the compiler know how to do the arithmetic to find the field it needs, by adding the necessary offset. In general memory objects are quite large, and a few 4 byte variables in the program reference quite a bit of memory.
(at the risk of oversimplification) Memory is sequential. Address 123 is the one-hundred and twenty third byte from the first (zeroth) by in the system. There is no memory devoted to indicating byte 123 is 123. The byte that comes after that is 124.
Here I have a few lines of delphi code running in delphi 7:
var
ptr:Pointer ;
begin
ptr:=AllocMem(40);
ptr:=Pchar('OneNationUnderGod');
if ptr<>nil then
FreeMem(ptr);
end;
Upon running this code snippet, FreeMem(ptr)will raise an error:'invalid pointer operation'. If I delete the sentence:
ptr:=Pchar('OneNationUnderGod');
then no error will occur. Now I have two questions,
1.Why is this happening? 2. If I have to use the Pchar sentence, how should I free the memory allocated earlier?
Much appreciation for your help!
The problem is that you are modifying the address held in the variable ptr.
You call AllocMem to allocate a buffer, which you refer to using ptr. That much is fine. But you must never change the value of ptr, the address of the buffer. And you do change it.
You wrote:
ptr:=AllocMem(40);
ptr:=Pchar('OneNationUnderGod');
The second line is the problem. You have modified ptr and now ptr refers to something else (a string literal held in read-only memory as it happens). You have now lost track of the buffer allocated by your call to AllocMem. You asked AllocMem for a new block of memory and then immediately discarded that block of memory.
What you presumably mean to do is to copy the string. Perhaps like this:
ptr := AllocMem(40);
StrCopy(ptr, 'OneNationUnderGod');
Now we are fine to call FreeMem, because ptr still contains the address that the call to AllocMem provided.
ptr := AllocMem(40);
try
StrCpy(ptr, 'OneNationUnderGod');
// do stuff with ptr
finally
FreeMem(ptr);
end;
Clearly in real code you would find a better and more robust way to specify buffer lengths than a hard-coded value.
In your code, assuming the above fix is applied, the test for ptr being nil is needless. AllocMem never returns nil. Failure of AllocMem results in an exception being raised.
Having said all that, it's not usual to operate on string buffers in this way. It is normal to use Delphi strings. If you need a PChar, for instance to use with interop, make one with PChar(str) where str is of type string.
You say that you must use dynamically allocated PChar buffers. Perhaps that is so, but I very much doubt it.
It crashes because you are freeing static memory that was not dynamically allocated. There is no need to free memory used by literals at all. Only free memory that is dynamically allocated.
I'd try to make what you've done more explicit. You seem to mistake the name of a variable with its value. However actually - considering values - what you did was
ptrA:=AllocMem(40);
ptrB:=Pchar('OneNationUnderGod');
if ptrB<>nil then
FreeMem(ptrB);
Every new assignment changes the value overwriting the previous one, thus you freeing another pointer that was allocated.
You may read documentation for functions like StrNew, StrDispose, StrCopy, StrLCopy and sample codes with those to see some patterns of working with PChar strings.
I was (purely out of curiosity) trying to find out what the size of an actual reference is when an allocation is made on the stack.
After reading this I still don't know (this answers it only for value types or type definitions), and I still cannot seem to find it anywhere.
So basically imagine a class as follows
class A
{
string a;
}
Now when an object of type A is instantiated, a reference to the string object would be stored on the stack, now what would the size of the allocation on the stack be?
Disclaimer: If I'm talking complete and utter nonsense please let me know :)
Just like the size of pointers, presumably, the size would be that of a native int: 32-bits on 32-bit platforms and 64-bits on a 64-bit platform.
It will be the size of IntPtr, either 32 or 64 bits, depending upon your environment.
Now when an object of type A is instantiated, a reference to the string object would be stored on the stack, now what would the size of the allocation on the stack be?
The string reference would in fact be stored on the heap, not the stack, since A is a reference type.