Is extra space allocated for variant records? - delphi

I'm working with the variant record below. The variable instance is Kro_Combi. SizeOf(Kro_Combi) reports 7812 bytes. SizeOf(Kro_Combi.data) reports 7810 bytes.
The sum of the SizeOf of all the other data structures composing the "non-directmode" case of the variant record also adds to 7810 bytes.
Why is there a two byte difference? I would like to have the two variant exactly overlay each other.
TKro_Combi = record
case directmode:boolean of
true : (
data : array[0..7809] of byte
);
false : (
Combi_Name : array[0..23] of char; //24
Gap1 : array[0..63] of byte; // 24-87 (64)
Ins_Effect_Group : array[1..12] of TIns_Effect_Params; //74 each, (Ins_Effect_Data=9 bytes) 74*12 = 888
Mast_Effect_Params : array[0..229] of byte; // 976-1205 : 230 bytes
Vect_Aud__Drum_Params : array[0..97] of byte; //1206-1303 : 98 bytes
Karma_Common : array[0..509] of byte; //1304-1813 : 510 bytes
Karma_Module : array[0..3] of TKarma_Module; //1814-2557 : 744 bytes each Total span 1814 - 4789 = 2976 bytes total
Common_Params : array[0..11] of byte; //4790-4801 = 12 bytes
Timbre_Group : array[1..16] of TTimbre_Params; ) // 4802 -4989 = 188 bytes each, 16 Timbres, 4802-7809 = 3008 bytes total for all
end;

First of all, there needs to be space for the directmode field. If you really want the record to have size 7810 bytes then you should remove that field. The other byte will be due to internal alignment and padding of the false part of the variant record. I can't yet quite work out where it comes from. No matter, you simply want to use a packed record to avoid any padding bytes.
TKro_Combi = packed record
case boolean of
true : (
data : array[0..7809] of byte
);
false : (
Combi_Name : array[0..23] of char; //24
Gap1 : array[0..63] of byte; // 24-87 (64)
Ins_Effect_Group : array[1..12] of TIns_Effect_Params; //74 each, (Ins_Effect_Data=9 bytes) 74*12 = 888
Mast_Effect_Params : array[0..229] of byte; // 976-1205 : 230 bytes
Vect_Aud__Drum_Params : array[0..97] of byte; //1206-1303 : 98 bytes
Karma_Common : array[0..509] of byte; //1304-1813 : 510 bytes
Karma_Module : array[0..3] of TKarma_Module; //1814-2557 : 744 bytes each Total span 1814 - 4789 = 2976 bytes total
Common_Params : array[0..11] of byte; //4790-4801 = 12 bytes
Timbre_Group : array[1..16] of TTimbre_Params; ) // 4802 -4989 = 188 bytes each, 16 Timbres, 4802-7809 = 3008 bytes total for all
end;

Related

Finding the Checksum Algorithm in this Serial Communication

Got a brainteaser for you! :)
I am working on trying to figuring out this serial communication between a microcontroller and a PC for several months and cannot seem to do it. 9600,N81 and I get no frame errors with my capture tool.
Hopefully someone out there can see these samples and it will click with them.
Sample 1
337795, IN,0xF0,0x5,0x62,0x0,0x0,0xA2,0xDE,0xF3,0x75,0xF3, Bytes = 9
337862,OUT,0xF0,0x5,0x63,0x0,0x1,0x1,0x2C,0x92,0xF3,0xF0,0xF3, Bytes = 10
338923, IN,0xF0,0x5,0x63,0x0,0x0,0x7E,0x84,0xF3,0x75,0xF3, Bytes = 9
338990,OUT,0xF0,0x5,0x64,0x0,0x1,0x1,0xD,0xC5,0xF3,0xF0,0xF3, Bytes = 10
340051, IN,0xF0,0x5,0x64,0x0,0x0,0x7B,0x8,0xF3,0x75,0xF3, Bytes = 9
340118,OUT,0xF0,0x5,0x65,0x0,0x1,0x1,0xB6,0xD9,0xF3,0xF0,0xF3, Bytes = 10
340499, IN,0xF0,0x0,0x65,0x5,0x3,0x1,0x1,0x0,0xAB,0xD3,0xF3,0x54,0xF3, Bytes = 12
340572,OUT,0xF0,0x5,0x66,0x0,0x1,0x1,0x7B,0xFC,0xF3,0xF0,0x5,0x66,0x3,0x4,0x4,0x1,0x8,0x3,0x2F,0x9E,0xF3,0xF3, Bytes = 21
340665, IN,0xF0,0x5,0x66,0x0,0x0,0xC3,0xBD,0xF3,0xAB,0xF3, Bytes = 9
340731,OUT,0xF0,0x5,0x67,0x0,0x1,0x1,0xC0,0xE0,0xF3,0xF0,0xF3, Bytes = 10
341794, IN,0xF0,0x5,0x67,0x0,0x0,0x1F,0xE7,0xF3,0xAB,0xF3, Bytes = 9
341860,OUT,0xF0,0x5,0x68,0x0,0x1,0x1,0x39,0x52,0xF3,0xF0,0xF3, Bytes = 10
342923, IN,0xF0,0x5,0x68,0x0,0x0,0xD8,0xAD,0xF3,0xAB,0xF3, Bytes = 9
342989,OUT,0xF0,0x5,0x69,0x0,0x1,0x1,0x82,0x4E,0xF3,0xF0,0xF3, Bytes = 10
344052, IN,0xF0,0x5,0x69,0x0,0x0,0x4,0xF7,0xF3,0xAB,0xF3, Bytes = 9
344118,OUT,0xF0,0x5,0x6A,0x0,0x1,0x1,0x4F,0x6B,0xF3,0xF0,0xF3, Bytes = 10
345180, IN,0xF0,0x5,0x6A,0x0,0x0,0x60,0x18,0xF3,0xAB,0xF3, Bytes = 9
345246,OUT,0xF0,0x5,0x6B,0x0,0x1,0x1,0xF4,0x77,0xF3,0xF0,0xF3, Bytes = 10
345627, IN,0xF0,0x0,0x6B,0x5,0x3,0x1,0x1,0x0,0x9,0xEA,0xF3,0x54,0xF3, Bytes = 12
345700,OUT,0xF0,0x5,0x6C,0x0,0x1,0x1,0xD5,0x20,0xF3,0xF0,0x5,0x6C,0x3,0x4,0x4,0x1,0x8,0x3,0x78,0x77,0xF3,0xF3, Bytes = 21
Sample 2
371435, IN,0xF0,0x5,0x8C,0x0,0x0,0x18,0xC7,0xF3,0x1A,0xF3, Bytes = 9
371502,OUT,0xF0,0x5,0x8D,0x0,0x1,0x1,0xE4,0x88,0xF3,0xF0,0xF3, Bytes = 10
372563, IN,0xF0,0x5,0x8D,0x0,0x0,0xC4,0x9D,0xF3,0x1A,0xF3, Bytes = 9
372630,OUT,0xF0,0x5,0x8E,0x0,0x1,0x1,0x29,0xAD,0xF3,0xF0,0xF3, Bytes = 10
373692, IN,0xF0,0x5,0x8E,0x0,0x0,0xA0,0x72,0xF3,0x1A,0xF3, Bytes = 9
373758,OUT,0xF0,0x5,0x8F,0x0,0x1,0x1,0x92,0xB1,0xF3,0xF0,0xF3, Bytes = 10
374820, IN,0xF0,0x5,0x8F,0x0,0x0,0x7C,0x28,0xF3,0x1A,0xF3, Bytes = 9
374887,OUT,0xF0,0x5,0x90,0x0,0x1,0x1,0xCA,0xC0,0xF3,0xF0,0xF3, Bytes = 10
375949, IN,0xF0,0x5,0x90,0x0,0x0,0x2E,0xE7,0xF3,0x1A,0xF3, Bytes = 9
376015,OUT,0xF0,0x5,0x91,0x0,0x1,0x1,0x71,0xDC,0xF3,0xF0,0xF3, Bytes = 10
376396, IN,0xF0,0x0,0x91,0x5,0x3,0x1,0x1,0x0,0xA4,0x3,0xF3,0xFD,0xF3, Bytes = 12
376469,OUT,0xF0,0x5,0x92,0x0,0x1,0x1,0xBC,0xF9,0xF3,0xF0,0x5,0x92,0x3,0x4,0x4,0x1,0x8,0x3,0x8,0x66,0xF3,0xF3, Bytes = 21
376562, IN,0xF0,0x5,0x92,0x0,0x0,0x96,0x52,0xF3,0xA4,0xF3, Bytes = 9
376628,OUT,0xF0,0x5,0x93,0x0,0x1,0x1,0x7,0xE5,0xF3,0xF0,0xF3, Bytes = 10
377692, IN,0xF0,0x5,0x93,0x0,0x0,0x4A,0x8,0xF3,0xA4,0xF3, Bytes = 9
377758,OUT,0xF0,0x5,0x94,0x0,0x1,0x1,0x26,0xB2,0xF3,0xF0,0xF3, Bytes = 10
378820, IN,0xF0,0x5,0x94,0x0,0x0,0x4F,0x84,0xF3,0xA4,0xF3, Bytes = 9
378887,OUT,0xF0,0x5,0x95,0x0,0x1,0x1,0x9D,0xAE,0xF3,0xF0,0xF3, Bytes = 10
379949, IN,0xF0,0x5,0x95,0x0,0x0,0x93,0xDE,0xF3,0xA4,0xF3, Bytes = 9
380015,OUT,0xF0,0x5,0x96,0x0,0x1,0x1,0x50,0x8B,0xF3,0xF0,0xF3, Bytes = 10
381077, IN,0xF0,0x5,0x96,0x0,0x0,0xF7,0x31,0xF3,0xA4,0xF3, Bytes = 9
381144,OUT,0xF0,0x5,0x97,0x0,0x1,0x1,0xEB,0x97,0xF3,0xF0,0xF3, Bytes = 10
381523, IN,0xF0,0x0,0x97,0x5,0x3,0x1,0x1,0x0,0x5E,0x1B,0x5B,0xF3,0xF3, Bytes = 12
I have more, if desired.
Some observations I've been able to see -
First, the numbers at the begging are aggregate timings in I think
nanoseconds. The 33* is 33 seconds.
Beginning byte 0xF0
Ending byte 0xF3
Sequence byte, the third byte of every packet increments by 1
It seems the destination device (noted as OUT) increments first and the
host (noted as IN) follows..
For the most part OUT packets are 10 bytes and IN packets are 9 bytes.
There are some times when this is not true and the packet can be 21 bytes..
Although I do notice a begin byte and end byte next to each other in the string of 21 bytes, the third byte (sequence#) does not increment.
I am not sure how to understand these longer packets.
This is a point to point communication, there are no other devices connected between these 2.
It is very chatty.
During my testing and probing, my test leads slipped between a couple of pins and killed the microcontroller. Thinking it would be a great project (and it is), I am attempting to recreate the functions of the original microcontroller. Which, I pretty much have done with the exception of the communication, figuring out what they are talking about and the checksum. I assume the second to the last byte is the checksum.
Thank you!
By omitting the begin (0xF0) and end (0xF3) bytes, Reversed CRC-CCITT is used to calculate the checksum.
Thanks to this website, I pasted in the bytes and found it - https://www.scadacore.com/tools/programming-calculators/online-checksum-calculator/

Decode UDP message with LUA

I'm relatively new to lua and programming in general (self taught), so please be gentle!
Anyway, I wrote a lua script to read a UDP message from a game. The structure of the message is:
DATAxXXXXaaaaBBBBccccDDDDeeeeFFFFggggHHHH
DATAx = 4 letter ID and x = control character
XXXX = integer shows the group of the data (groups are known)
aaaa...HHHHH = 8 single-precision floating point numbers
The last ones is those numbers I need to decode.
If I print the message as received, it's something like:
DATA*{V???A?A?...etc.
Using string.byte(), I'm getting a stream of bytes like this (I have "formatted" the bytes to reflect the structure above.
68 65 84 65/42/20 0 0 0/237 222 28 66/189 59 182 65/107 42 41 65/33 173 79 63/0 0 128 63/146 41 41 65/0 0 30 66/0 0 184 65
The first 5 bytes are of course the DATA*. The next 4 are the 20th group of data. The next bytes, the ones I need to decode, and are equal to those values:
237 222 28 66 = 39.218
189 59 182 65 = 22.779
107 42 41 65 = 10.573
33 173 79 63 = 0.8114
0 0 128 63 = 1.0000
146 41 41 65 = 10.573
0 0 30 66 = 39.500
0 0 184 65 = 23.000
I've found C# code that does the decode with BitConverter.ToSingle(), but I haven't found any like this for Lua.
Any idea?
What Lua version do you have?
This code works in Lua 5.3
local str = "DATA*\20\0\0\0\237\222\28\66\189\59\182\65..."
-- Read two float values starting from position 10 in the string
print(string.unpack("<ff", str, 10)) --> 39.217700958252 22.779169082642 18
-- 18 (third returned value) is the next position in the string
For Lua 5.1 you have to write special function (or steal it from François Perrad's git repo )
local function binary_to_float(str, pos)
local b1, b2, b3, b4 = str:byte(pos, pos+3)
local sign = b4 > 0x7F and -1 or 1
local expo = (b4 % 0x80) * 2 + math.floor(b3 / 0x80)
local mant = ((b3 % 0x80) * 0x100 + b2) * 0x100 + b1
local n
if mant + expo == 0 then
n = sign * 0.0
elseif expo == 0xFF then
n = (mant == 0 and sign or 0) / 0
else
n = sign * (1 + mant / 0x800000) * 2.0^(expo - 0x7F)
end
return n
end
local str = "DATA*\20\0\0\0\237\222\28\66\189\59\182\65..."
print(binary_to_float(str, 10)) --> 39.217700958252
print(binary_to_float(str, 14)) --> 22.779169082642
It’s little-endian byte-order of IEEE-754 single-precision binary:
E.g., 0 0 128 63 is:
00111111 10000000 00000000 00000000
(63) (128) (0) (0)
Why that equals 1 requires that you understand the very basics of IEEE-754 representation, namely its use of an exponent and mantissa. See here to start.
See #Egor‘s answer above for how to use string.unpack() in Lua 5.3 and one possible implementation you could use in earlier versions.

Getting the stack pointer content using Intel's PinTool

Using objdump utility, we are able to retrieved the relative address of a variable for example consider a simple C program:
Source-code:
#include<stdio.h>
void do_stuff(int my_arg){
int my_local=my_arg+2;
int i;
for(i=0;i<my_local;i++)
printf("i=%d\n",i);
}
int main(){
do_stuff(2);
return 0;
}
Compile with gcc :
$ gcc -g example.c -o example
Run objdump utility with dwarf flag for ELF information.
$objdump --dwarf=info example
Output:
Contents of the .debug_info section:
Compilation Unit # offset 0x0:
Length: 0xd3 (32-bit)
Version: 4
Abbrev Offset: 0x0
Pointer Size: 8
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
<c> DW_AT_producer : (indirect string, offset: 0x0): GNU C 4.8.4 -mtune=generic -march=x86-64 -g -fstack-protector
<10> DW_AT_language : 1 (ANSI C)
<11> DW_AT_name : (indirect string, offset: 0xcd): sample1.c
<15> DW_AT_comp_dir : (indirect string, offset: 0x7e): /home/bernard/PhD/TEJAS/tejas_installation_kit/Tejas-Simulator/Tejas/benchmark
<19> DW_AT_low_pc : 0x40052d
<21> DW_AT_high_pc : 0x54
<29> DW_AT_stmt_list : 0x0
<1><2d>: Abbrev Number: 2 (DW_TAG_base_type)
<2e> DW_AT_byte_size : 8
<2f> DW_AT_encoding : 7 (unsigned)
<30> DW_AT_name : (indirect string, offset: 0x47): long unsigned int
<1><34>: Abbrev Number: 2 (DW_TAG_base_type)
<35> DW_AT_byte_size : 1
<36> DW_AT_encoding : 8 (unsigned char)
<37> DW_AT_name : (indirect string, offset: 0x62): unsigned char
<1><3b>: Abbrev Number: 2 (DW_TAG_base_type)
<3c> DW_AT_byte_size : 2
<3d> DW_AT_encoding : 7 (unsigned)
<3e> DW_AT_name : (indirect string, offset: 0xde): short unsigned int
<1><42>: Abbrev Number: 2 (DW_TAG_base_type)
<43> DW_AT_byte_size : 4
<44> DW_AT_encoding : 7 (unsigned)
<45> DW_AT_name : (indirect string, offset: 0x4c): unsigned int
<1><49>: Abbrev Number: 2 (DW_TAG_base_type)
<4a> DW_AT_byte_size : 1
<4b> DW_AT_encoding : 6 (signed char)
<4c> DW_AT_name : (indirect string, offset: 0x64): signed char
<1><50>: Abbrev Number: 2 (DW_TAG_base_type)
<51> DW_AT_byte_size : 2
<52> DW_AT_encoding : 5 (signed)
<53> DW_AT_name : (indirect string, offset: 0xf1): short int
<1><57>: Abbrev Number: 3 (DW_TAG_base_type)
<58> DW_AT_byte_size : 4
<59> DW_AT_encoding : 5 (signed)
<5a> DW_AT_name : int
<1><5e>: Abbrev Number: 2 (DW_TAG_base_type)
<5f> DW_AT_byte_size : 8
<60> DW_AT_encoding : 5 (signed)
<61> DW_AT_name : (indirect string, offset: 0x75): long int
<1><65>: Abbrev Number: 2 (DW_TAG_base_type)
<66> DW_AT_byte_size : 8
<67> DW_AT_encoding : 7 (unsigned)
<68> DW_AT_name : (indirect string, offset: 0xfb): sizetype
<1><6c>: Abbrev Number: 2 (DW_TAG_base_type)
<6d> DW_AT_byte_size : 1
<6e> DW_AT_encoding : 6 (signed char)
<6f> DW_AT_name : (indirect string, offset: 0x6b): char
<1><73>: Abbrev Number: 4 (DW_TAG_subprogram)
<74> DW_AT_external : 1
<74> DW_AT_name : (indirect string, offset: 0x59): do_stuff
<78> DW_AT_decl_file : 1
<79> DW_AT_decl_line : 2
<7a> DW_AT_prototyped : 1
<7a> DW_AT_low_pc : 0x40052d
<82> DW_AT_high_pc : 0x3f
<8a> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)
<8c> DW_AT_GNU_all_tail_call_sites: 1
<8c> DW_AT_sibling : <0xb9>
<2><90>: Abbrev Number: 5 (DW_TAG_formal_parameter)
<91> DW_AT_name : (indirect string, offset: 0xd7): my_arg
<95> DW_AT_decl_file : 1
<96> DW_AT_decl_line : 2
<97> DW_AT_type : <0x57>
<9b> DW_AT_location : 2 byte block: 91 5c (DW_OP_fbreg: -36)
<2><9e>: Abbrev Number: 6 (DW_TAG_variable)
<9f> DW_AT_name : (indirect string, offset: 0x3e): my_local
<a3> DW_AT_decl_file : 1
<a4> DW_AT_decl_line : 3
<a5> DW_AT_type : <0x57>
<a9> DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
<2><ac>: Abbrev Number: 7 (DW_TAG_variable)
<ad> DW_AT_name : i
<af> DW_AT_decl_file : 1
<b0> DW_AT_decl_line : 4
<b1> DW_AT_type : <0x57>
<b5> DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24)
<2><b8>: Abbrev Number: 0
<1><b9>: Abbrev Number: 8 (DW_TAG_subprogram)
<ba> DW_AT_external : 1
<ba> DW_AT_name : (indirect string, offset: 0x70): main
<be> DW_AT_decl_file : 1
<bf> DW_AT_decl_line : 9
<c0> DW_AT_type : <0x57>
<c4> DW_AT_low_pc : 0x40056c
<cc> DW_AT_high_pc : 0x15
<d4> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)
<d6> DW_AT_GNU_all_tail_call_sites: 1
<1><d6>: Abbrev Number: 0
I want to do as follows:-
I want to retrieved the address of a variable , say my_local. First I will look into DW_TAG_Variable, then DW_AT_name, DW_AT_location which was given by base register at function -20 from the top.
Question:
How to know the content of base register at run time.
Can we implement it using PinTool.
Question in broader sense:
I want variable my_local map to which address in memory given information from dwarf and Pintool.
Thanks in Advance.
You should be able to use Pin's SafeCopy function to access app memory and copy it into pintool memory.
But as noted in the comments, it's not always possible to know where variable values are stored reliably so keep this in mind.

Delphi Set Invalid Typecast

How do I fix this invalid typecast error? The code works when the set has less than 31 items. Below is the code snippet:
type
TOptionsSurveyTypes=(
ostLoadSurvey00,
ostLoadSurvey01,
ostLoadSurvey02,
ostLoadSurvey03,
ostLoadSurvey04,
ostLoadSurvey05,
ostLoadSurvey06,
ostLoadSurvey07,
ostLoadSurvey08,
ostLoadSurvey09,
ostLoadSurvey10,
ostEventLog01,
ostEventLog02,
ostEventLog03,
ostEventLog04,
ostEventLog05,
ostSagSwell,
ostTamper,
ostWaveforms,
ostDeviceList,
ostDeleteData,
ostTOUBillingTotal,
ostTOUPrevious,
ostProfileGenericLoadSurvey01,
ostProfileGenericLoadSurvey02,
ostProfileGenericLoadSurvey03,
ostProfileGenericLoadSurvey04,
ostProfileGenericLoadSurvey05,
ostProfileGenericLoadSurvey06,
ostProfileGenericLoadSurvey07,
ostProfileGenericLoadSurvey08,
ostProfileGenericLoadSurvey09,
ostProfileGenericLoadSurvey10,
ostProfileGenericEventLog01,
ostProfileGenericEventLog02,
ostProfileGenericEventLog03,
ostProfileGenericEventLog04,
ostProfileGenericEventLog05,
ostProfileGenericBillingTotal,
ostProfileGenericPrevious,
ostProfileGeneric
);
TOptionsSurveyTypesSet=set of TOptionsSurveyTypes;
function TUserProcessRollback.SurveyRollBack:boolean;
var
vRollbackDate: TDateTime;
FOptions: LongWord;
begin
...
if ostDeleteData in TOptionsSurveyTypesSet(FOptions) then <-- invalid typecast error here
vRollbackDate := 0.00
else
vRollbackDate := FRollbackDate;
...
end;
When I reduce the set to just less than 32 items and FOptions is declared as DWORD, the code compiles .
Thanks
Your enumerated type has 41 items. Each byte holds 8 bits. To have a set of this enumerated type requires at least 41 bits. The smallest number of bytes necessary to hold 41 bits is 6. So the set type is 6 bytes. To confirm this, you can execute this:
ShowMessage ( inttostr ( sizeof ( TOptionsSurveyTypesSet ) ) );
A DWORD is 4 bytes, so it cannot be typecast into a type that is 6 bytes. If you declare fOptions to be a type with 6 bytes, your code will compile.
FOptions: packed array [ 1 .. 6] of byte;
If you reduce the enumerated type to 32 or fewer items, then the set type will be 4 bytes, and so the typecast from DWORD will work.

Golang append memory allocation VS. STL push_back memory allocation

I compared the Go append function and the STL vector.push_back and found that different memory allocation strategy which confused me. The code is as follow:
// CPP STL code
void getAlloc() {
vector<double> arr;
int s = 9999999;
int precap = arr.capacity();
for (int i=0; i<s; i++) {
if (precap < i) {
arr.push_back(rand() % 12580 * 1.0);
precap = arr.capacity();
printf("%d %p\n", precap, &arr[0]);
} else {
arr.push_back(rand() % 12580 * 1.0);
}
}
printf("\n");
return;
}
// Golang code
func getAlloc() {
arr := []float64{}
size := 9999999
pre := cap(arr)
for i:=0; i<size; i++ {
if pre < i {
arr = append(arr, rand.NormFloat64())
pre = cap(arr)
log.Printf("%d %p\n", pre, &arr)
} else {
arr = append(arr, rand.NormFloat64())
}
}
return;
}
But the memory address is invarient to the increment of size expanding, this really confused me.
By the way, the memory allocation strategy is different in this two implemetation (STL VS. Go), I mean the expanding size. Is there any advantage or disadvantage? Here is the simplified output of code above[size and first element address]:
Golang CPP STL
2 0xc0800386c0 2 004B19C0
4 0xc0800386c0 4 004AE9B8
8 0xc0800386c0 6 004B29E0
16 0xc0800386c0 9 004B2A18
32 0xc0800386c0 13 004B2A68
64 0xc0800386c0 19 004B2AD8
128 0xc0800386c0 28 004B29E0
256 0xc0800386c0 42 004B2AC8
512 0xc0800386c0 63 004B2C20
1024 0xc0800386c0 94 004B2E20
1280 0xc0800386c0 141 004B3118
1600 0xc0800386c0 211 004B29E0
2000 0xc0800386c0 316 004B3080
2500 0xc0800386c0 474 004B3A68
3125 0xc0800386c0 711 004B5FD0
3906 0xc0800386c0 1066 004B7610
4882 0xc0800386c0 1599 004B9768
6102 0xc0800386c0 2398 004BC968
7627 0xc0800386c0 3597 004C1460
9533 0xc0800386c0 5395 004B5FD0
11916 0xc0800386c0 8092 004C0870
14895 0xc0800386c0 12138 004D0558
18618 0xc0800386c0 18207 004E80B0
23272 0xc0800386c0 27310 0050B9B0
29090 0xc0800386c0 40965 004B5FD0
36362 0xc0800386c0 61447 00590048
45452 0xc0800386c0 92170 003B0020
56815 0xc0800386c0 138255 00690020
71018 0xc0800386c0 207382 007A0020
....
UPDATE:
See comments for Golang memory allocation strategy.
For STL, the strategy depends on the implementation. See this post for further information.
Your Go and C++ code fragments are not equivalent. In the C++ function, you are printing the address of the first element in the vector, while in the Go example you are printing the address of the slice itself.
Like a C++ std::vector, a Go slice is a small data type that holds a pointer to an underlying array that holds the data. That data structure has the same address throughout the function. If you want the address of the first element in the slice, you can use the same syntax as in C++: &arr[0].
You're getting the pointer to the slice header, not the actual backing array. You can think of the slice header as a struct like
type SliceHeader struct {
len,cap int
backingArray unsafe.Pointer
}
When you append and the backing array is reallocated, the pointer backingArray will likely be changed (not necessarily, but probably). However, the location of the struct holding the length, cap, and pointer to the backing array doesn't change -- it's still on the stack right where you declared it. Try printing &arr[0] instead of &arr and you should see behavior closer to what you expect.
This is pretty much the same behavior as std::vector, incidentally. Think of a slice as closer to a vector than a magic dynamic array.

Resources