Page 1 of 1
Add a map element on access the map with new key
Posted: Sun Mar 04, 2018 4:33 pm
by danilocoelho
This example of code is based in help AddMapElement().
I'm use PureBasic 5.62 (Linux - x64).
Please see my question in the code comments.
Code: Select all
Structure Country_
name.s
continent.s
EndStructure
NewMap Country.Country_()
; Regular way to add an element
With Country("US")
\name = "United States"
\continent = "America"
EndWith
Debug "Map Element US = " + @Country()
; The same using AddMapElement()
Define *france.Country_ = AddMapElement(Country(), "FR")
With *france
\name = "France"
\continent = "Europe"
EndWith
Debug "Map Element *france = " + *france
; Not documented way, but similar the regular way.
; This key don't exists then new map element is created and pointer returned as expected! Exactly as AddMapElement...
Define *brazil.Country_ = Country("BR")
*brazil\name = "Brazil"
*brazil\continent = "America"
Debug "Map Element *brazil = " + *brazil
; But new map element isn't accessible
ForEach Country()
Debug Country()\name + " - " + Country()\continent + " | Pointer = " + @Country()
Next
Debug "FindMapElement BR = " + FindMapElement(Country(), "BR")
Debug "MapSize = " + MapSize(Country())
Even considering this part of the documentation:
Remarks
This function is not mandatory when dealing with maps, the elements are automatically added when affecting them.
I think accessing the map with a new key should implicitly invoke AddMapElement or return #Null as it does in FindMapElement.
What do you think?
Att,
Danilo S. Coelho.
Re: Add a map element on access the map with new key
Posted: Sun Mar 04, 2018 5:51 pm
by Micoute
Define *brazil.Country_ = AddMapElement(Country(),"BR")
Re: Add a map element on access the map with new key
Posted: Mon Mar 05, 2018 10:32 am
by danilocoelho
Micoute wrote:Define *brazil.Country_ = AddMapElement(Country(),"BR")
Micoute, thank you for replying.
I understand that by using AddMapElement explicitly there is no problem.
This is not the point I am proposing to discuss.
I recognize that I am trying to add an element to the map in an undocumented way. For me, it is clear in the documentation that the element will be added to the map when I access a new key and assign some value to any member of the structure.
At this point, I would like the opinions of PureBasic users and evaluate the possibility of improving this undefined behavior.
When I access a new key in map and do not assign value to any member of the structure, I instead get a pointer to a new element that I thought would be created, it is valid, I can access the members of the structure and assign value to any member . However, as demonstrated in this example, the allocated structure was not included in the map.
Code: Select all
; Not documented way, but similar the regular way.
; This key don't exists then new map element is created and pointer returned as expected! Exactly as AddMapElement...
Define *brazil.Country_ = Country("BR")
*brazil\name = "Brazil"
*brazil\continent = "America"
Debug "Map Element *brazil = " + *brazil
; But new map element isn't accessible
ForEach Country()
Debug Country()\name + " - " + Country()\continent + " | Pointer = " + @Country()
Next
Debug "FindMapElement BR = " + FindMapElement(Country(), "BR")
Debug "MapSize = " + MapSize(Country())
Could I be clear?
Sorry for my English, using google translate here.
Re: Add a map element on access the map with new key
Posted: Mon Mar 05, 2018 11:54 am
by said
Hi,
The common way is the documented way as mentioned by Micoute using AddMapElement()
However, i think it depends on whteher the map is on the left hand side of right hand side ... it has been discussed previousely, you can search the forums (not easy i know

)
Look at this
Code: Select all
Structure Country_
name.s
continent.s
EndStructure
NewMap Country.Country_()
; Not documented way, but similar the regular way.
; This key don't exists then new map element is created and pointer returned as expected! Exactly as AddMapElement...
Define *brazil.Country_
If Country("BR") ; < --- this ensures the proper allocation of the structure Country_
*brazil = Country()
EndIf
*brazil\name = "Brazil"
*brazil\continent = "America"
Debug "Map Element *brazil = " + *brazil
; But new map element isn't accessible
ForEach Country()
Debug ">>> " + Country()\name + " - " + Country()\continent + " | Pointer = " + @Country()
Next
Debug "FindMapElement BR = " + FindMapElement(Country(), "BR")
Debug "MapSize = " + MapSize(Country())
Re: Add a map element on access the map with new key
Posted: Mon Mar 05, 2018 12:37 pm
by nco2k
y'all are missing the point. its a bug in my opinion:
Code: Select all
Structure MyStruc
Foo.b
EndStructure
NewMap MyMap.MyStruc()
Debug MyMap("Test")
the map is empty, so what exactly is that pointer pointing to? the map itself? it would be better to simply return 0, to avoid confusion.
c ya,
nco2k
Re: Add a map element on access the map with new key
Posted: Mon Mar 05, 2018 12:53 pm
by said
nco2k wrote:y'all are missing the point. its a bug in my opinion:
Code: Select all
Structure MyStruc
Foo.b
EndStructure
NewMap MyMap.MyStruc()
Debug MyMap("Test")
the map is empty, so what exactly is that pointer pointing to? the map itself? it would be better to simply return 0, to avoid confusion.
c ya,
nco2k
I highly value your opinions nco2k

they are mostly very accurate
For me this is quite confusing and i also prefer if the return was simply 0
Re: Add a map element on access the map with new key
Posted: Mon Mar 05, 2018 5:46 pm
by #NULL
nco2k wrote:Code: Select all
Structure MyStruc
Foo.b
EndStructure
NewMap MyMap.MyStruc()
Debug MyMap("Test")
the map is empty, so what exactly is that pointer pointing to?
Its not empty, the key will be added to the map. Maybe you're saying it shouldn't be added?
Anyway it doesn't make sense that in the following 'a' is added to the map but 'b' and 'c' are not:
Code: Select all
NewMap m.s()
m("a")
Debug FindMapElement(m(), "a")
b.s = m("b")
Debug FindMapElement(m(), "b")
c = @m("c")
Debug FindMapElement(m(), "c")
ForEach m()
Debug "m: " + MapKey(m())
Next
Re: Add a map element on access the map with new key
Posted: Mon Mar 05, 2018 6:02 pm
by #NULL
#NULL wrote:Its not empty, the key will be added to the map.
I was wrong. You are right. I tested without the Debug i guess.
Re: Add a map element on access the map with new key
Posted: Mon Mar 05, 2018 6:06 pm
by nco2k
#NULL wrote:Its not empty, the key will be added to the map.
no it wont.
this reads the element:
this sets the element:
but yea, i should have written it like this, to demonstrate the problem more properly:
Code: Select all
Structure MyStruc
Foo.b
EndStructure
NewMap MyMap.MyStruc()
*Addr = MyMap("Test")
Debug *Addr
Debug FindMapElement(MyMap(), "Test")
Debug MapSize(MyMap())
however, this problem only occurs with structured maps, which you dont use in your example.
without a structure, the return value will simply be 0 or an empty string, depending on the type of the map:
Code: Select all
NewMap MyString$()
Debug MyString$("Foo")
NewMap MyLong.l()
Debug MyLong("Bar")
c ya,
nco2k
Re: Add a map element on access the map with new key
Posted: Tue Mar 06, 2018 12:52 am
by danilocoelho
Thank you nco2k for your objectivity.
My opinion is also that this is a bug.
However, because I am a newbie user in the forum I prefer to expose the situation before reporting.
By the way, how to report the bug?
Can anyone test on Mac OS and Windows?
Code: Select all
Structure MyStruc
Foo.b
EndStructure
NewMap MyMap.MyStruc()
*Addr = MyMap("Test")
Debug *Addr
Debug FindMapElement(MyMap(), "Test")
Debug MapSize(MyMap())
I believe this happens on all platforms.
Re: Add a map element on access the map with new key
Posted: Tue Mar 06, 2018 5:08 am
by nco2k
no thats fine. its never wrong to first discuss things in the coding section, before posting it as a bug. just go to the "Bugs - Windows" section here on the forum, and create a new topic with a short example code, and maybe even the link to this thread. the team will investigate and respond. it might take a week, it might take a year. this isnt really a high priority issue, but the team will read every bug report for sure. hell, im certain that fred already saw this thread, but stuff outside of the bugs section will easily be forgotten, as its impossible to keep track of all the discussions across the board.
or maybe one of the mods could simply move this thread to the bugs section? i would do it myself, but im not a mod.
c ya,
nco2k
Re: Add a map element on access the map with new key
Posted: Sun Mar 25, 2018 4:26 pm
by danilocoelho
In this
topic I'm use valgrind for detect memory leak.
I investigated this bug with this example of code:
Code: Select all
Structure MyStruc
Foo.s
List dependencies.MyStruc()
EndStructure
Procedure main()
If OpenConsole()
PrintN("Basic program...")
Protected NewMap MyMap.MyStruc()
Protected *new_map_element.MyStruc = MyMap("Test")
PrintN("*new_map_element: " + *new_map_element)
AddElement(*new_map_element\dependencies()) ; <----- memory leak here!
*new_map_element\dependencies()\Foo = "Test"; <----- memory leak here!
PrintN("SizeOf(*new_map_element): " + SizeOf(*new_map_element))
PrintN("FindMapElement: " + FindMapElement(MyMap(), "Test"))
PrintN("MapSize: " + MapSize(MyMap()))
CloseConsole()
EndIf
EndProcedure
main()
Valgrind memory leak check:
Code: Select all
danilo@pc-linux-mint ~/workspace/gitlab/projetos_bin $ valgrind --leak-check=yes ./console_basic
==5247== Memcheck, a memory error detector
==5247== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==5247== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==5247== Command: ./console_basic
==5247==
Basic program...
*new_map_element: 88213736
SizeOf(*new_map_element): 8
FindMapElement: 0
MapSize: 0
==5247==
==5247== HEAP SUMMARY:
==5247== in use at exit: 1,194 bytes in 6 blocks
==5247== total heap usage: 44 allocs, 38 frees, 25,639 bytes allocated
==5247==
==5247== 18 bytes in 1 blocks are possibly lost in loss record 1 of 6
==5247== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5247== by 0x4050C1: SYS_FastAllocateStringFree4 (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x40217C: ??? (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x500006D01: ???
==5247== by 0x8A3B000004BE: ???
==5247== by 0x10004157F1C02FF: ???
==5247== by 0x170F12FF1A1311FE: ???
==5247== by 0xFF15: ???
==5247== by 0x541F6B7: ???
==5247== by 0x54208E7: ???
==5247==
==5247== 48 bytes in 1 blocks are possibly lost in loss record 2 of 6
==5247== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5247== by 0x40451D: SYS_AllocateMemory (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4045CC: SYS_AllocateMemoryWithSize (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x403261: PB_Object_CreateAllocator (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x402BD9: PB_NewMap (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4020C5: ??? (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x541F64F: ???
==5247== by 0x4023BC: PB_PrintN (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x402095: ??? (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x500006D01: ???
==5247== by 0x8A3B000004BE: ???
==5247== by 0x10004157F1C02FF: ???
==5247==
==5247== 104 bytes in 1 blocks are possibly lost in loss record 3 of 6
==5247== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5247== by 0x40451D: SYS_AllocateMemory (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4045CC: SYS_AllocateMemoryWithSize (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4032F9: PB_Object_CreateAllocator (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x403282: PB_Object_CreateAllocator (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x402BD9: PB_NewMap (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4020C5: ??? (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x541F64F: ???
==5247== by 0x4023BC: PB_PrintN (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x402095: ??? (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x500006D01: ???
==5247== by 0x8A3B000004BE: ???
==5247==
==5247== 104 bytes in 1 blocks are possibly lost in loss record 4 of 6
==5247== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5247== by 0x40451D: SYS_AllocateMemory (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4045CC: SYS_AllocateMemoryWithSize (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x40265D: PB_NewList (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x404390: SYS_InitDynamicStructure (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x40254F: PB_AddElement (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x402160: ??? (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x500006D01: ???
==5247== by 0x8A3B000004BE: ???
==5247== by 0x10004157F1C02FF: ???
==5247== by 0x170F12FF1A1311FE: ???
==5247== by 0xFF15: ???
==5247==
==5247== 104 bytes in 1 blocks are definitely lost in loss record 5 of 6
==5247== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5247== by 0x40451D: SYS_AllocateMemory (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4045CC: SYS_AllocateMemoryWithSize (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x40265D: PB_NewList (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x404390: SYS_InitDynamicStructure (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x402A54: PB_GetMapElement (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4020DF: ??? (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x500006D01: ???
==5247== by 0x8A3B000004BE: ???
==5247== by 0x10004157F1C02FF: ???
==5247== by 0x170F12FF1A1311FE: ???
==5247== by 0xFF15: ???
==5247==
==5247== 816 bytes in 1 blocks are possibly lost in loss record 6 of 6
==5247== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5247== by 0x40451D: SYS_AllocateMemory (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4045CC: SYS_AllocateMemoryWithSize (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4034C8: PB_Object_BlockAlloc (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x4024CF: PB_AddElement (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x402160: ??? (in /home/danilo/workspace/gitlab/projetos_bin/console_basic)
==5247== by 0x500006D01: ???
==5247== by 0x8A3B000004BE: ???
==5247== by 0x10004157F1C02FF: ???
==5247== by 0x170F12FF1A1311FE: ???
==5247== by 0xFF15: ???
==5247== by 0x541F6B7: ???
==5247==
==5247== LEAK SUMMARY:
==5247== definitely lost: 104 bytes in 1 blocks
==5247== indirectly lost: 0 bytes in 0 blocks
==5247== possibly lost: 1,090 bytes in 5 blocks
==5247== still reachable: 0 bytes in 0 blocks
==5247== suppressed: 0 bytes in 0 blocks
==5247==
==5247== For counts of detected and suppressed errors, rerun with: -v
==5247== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
nco2k wrote that this is not really a high priority issue, but we should also consider the memory leak ... and the difficulty of finding this kind of bug.
Please can any moderator move this topic to the bug section?
Thank you.