Raised This Month: $12 Target: $400
 3% 

[Solved]Floats getting lost in IBasicTrie


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
WildCard65
Veteran Member
Join Date: Aug 2013
Location: Canada
Old 07-18-2014 , 08:50   [Solved]Floats getting lost in IBasicTrie
Reply With Quote #1

Somehow, my extension is loosing floats inside an IBasicTrie, I have ran 2 tests on the trie that the float is stored into(with same key) when it was inserted(in the functions that inserted them), and both passed with successful grabbing float, but the function that needs it is failing to retrieve it from exact same pointer, exact same key(I made sure Retrieve returns true by having it in an !<trie pointer var>->Retrieve("defaultValue", &vp)) //vp is a void pointer. The if gets false meaning Retrieve returned true so it means key exists, but it suppose to return a float like 5.00000 but instead I recieve 0.0000

Source: https://github.com/WildCard65/FF2-Al.../extension.cpp

Solved by converting every usage of IBasicTrie and CellArray over to StringHashMap(in sm_stringhashmap.h) and ke::Vector(typed to ke::AString) then storing the floats in the map as cell_t

Last edited by WildCard65; 07-21-2014 at 09:55.
WildCard65 is offline
VoiDeD
AlliedModders Donor
Join Date: Mar 2009
Location: Illinois, USA
Old 07-18-2014 , 15:55   Re: Floats getting lost in IBasicTrie
Reply With Quote #2

Here's the most honest, blunt, and straight-to-the-truth tip anyone can give you:

Stop. You're not qualified to write SM extensions.

Here's your issues:
1) You're trying to write sourcepawn within c++ code. IBasicTrie? For what purpose? AMTL provides templated containers (HashMap, HashSet, HashTable, etc). Valve provides templated containers (CUtlvector, CUtlMap, etc). Even the STL provides templated containers (which, however, you shouldn't really be using within the Valve ecosystem).
2) You're writing buggy code and then questioning the behavior of the containers which both AM and Valve use exclusively throughout their code with zero issues.

Personally, I believe whatever problem you're trying to solve with an extension doesn't actually exist, and you're creating this amalgamation of SP and C++ which: will be buggy, will crash servers, and will give people headaches.
__________________
VoiDeD is offline
WildCard65
Veteran Member
Join Date: Aug 2013
Location: Canada
Old 07-18-2014 , 17:09   Re: Floats getting lost in IBasicTrie
Reply With Quote #3

Quote:
Originally Posted by VoiDeD View Post
Personally, I believe whatever problem you're trying to solve with an extension doesn't actually exist
If your sure about that, then explain how a plugin would know if another plugin gets unloaded if the plugin wanting to know doesn't depend on it but the plugin it wants to know if it's unload actually depends on the plugin wanting to know.

And from what I've just looked up in script functions, there is straight forward forward that does that, instead, there's a iterators one could use, EXCEPT, it doesn't allow one to easily disquinish a plugin of interest from another plugin. Going by files isn't reliable also.

Another thing that relates to what I just said, plugin handles aren't reliable to store becuase they get freed upon plugin unload(that goes for IPlugin pointers, but atleast extensions can hook with plugin listeners to know when plugins load/unload which allows me to always have a valid pointer to the same plugin).

Another thing: I am storing IBasicTries inside of IBasicTries where with vectors, they are restricted to 1 type only(ke::Vector and CUtlVector) making it pointless to do what IBasicTries can do, plus you can't have a pointer to a vector without a bridge class.
Sure I can always set vector type to void* but how would one turn a vector into a void*

Last edited by WildCard65; 07-18-2014 at 17:11.
WildCard65 is offline
BAILOPAN
Join Date: Jan 2004
Old 07-18-2014 , 17:31   Re: Floats getting lost in IBasicTrie
Reply With Quote #4

The problem you're encountering is basic misunderstanding of C++'s memory model:

PHP Code:
inline void *ftovp(float val)
{
    
float *fp = (float*)&val;
    return (
void*)fp;

You are returning a pointer that immediately becomes invalid memory. I'd be very surprised if the compiler wasn't warning you about this (I strongly suspect GCC or Clang would throw a fit - not sure about VC). The address of &val becomes undefined once the function scope ends.

We discourage writing extensions because they are very complex to write and maintain - and we also discourage using unsafe containers like IBasicTrie. That's not to discourage from using and experimenting with C++, but rather we want released extensions be very high-quality so SourceMod's stability and reliability are not held in question. If you want to release extensions you should use safe containers like ke::HashMap and learn about RAII, pointers, and memory management.
__________________
egg

Last edited by BAILOPAN; 07-18-2014 at 17:32.
BAILOPAN is offline
VoiDeD
AlliedModders Donor
Join Date: Mar 2009
Location: Illinois, USA
Old 07-18-2014 , 17:35   Re: Floats getting lost in IBasicTrie
Reply With Quote #5

Quote:
Originally Posted by WildCard65 View Post
If your sure about that, then explain how a plugin would know if another plugin gets unloaded if the plugin wanting to know doesn't depend on it but the plugin it wants to know if it's unload actually depends on the plugin wanting to know.
I can't interpret what use case you're describing there, but I can suggest using the existing dependency system that exists: RegPluginLibrary, OnLibraryAdded, OnLibraryRemoved. This should give you everything you need for plugins to know about each other.

Quote:
Originally Posted by WildCard65 View Post
Another thing that relates to what I just said, plugin handles aren't reliable to store becuase they get freed upon plugin unload(that goes for IPlugin pointers, but atleast extensions can hook with plugin listeners to know when plugins load/unload which allows me to always have a valid pointer to the same plugin).
Then don't store plugin handles. OnLibraryAdded/Removed will tell you when plugins are loaded and unloaded.

Quote:
Originally Posted by WildCard65 View Post
Another thing: I am storing IBasicTries inside of IBasicTries where with vectors, they are restricted to 1 type only(ke::Vector and CUtlVector) making it pointless to do what IBasicTries can do, plus you can't have a pointer to a vector without a bridge class.
IBasicTries are able to do what you're describing because they're entirely not type safe. You don't know what data types you're working with when you extract a value out of them. The telltale sign of not having type safety is when you start performing casts between unrelated types.

This is no different than using a void pointer as your value type with the type safe containers (AM's, Valve's).

But why do you need a nested data structure?

Quote:
Originally Posted by WildCard65 View Post
Sure I can always set vector type to void* but how would one turn a vector into a void*
This is normally done with casting, see reinterpret_cast. You should also read up on why you should generally never be doing this kind of cast unless you understand what you're doing.


However, I think the root issue is that you're approaching this with the XY problem. You'd like to be able to work with plugin dependencies (the X), but you're not familiar how that's done so instead you work through the solution with something entirely different: a c++ extension for managing plugins (the Y).
__________________

Last edited by VoiDeD; 07-18-2014 at 17:38.
VoiDeD is offline
WildCard65
Veteran Member
Join Date: Aug 2013
Location: Canada
Old 07-18-2014 , 18:32   Re: Floats getting lost in IBasicTrie
Reply With Quote #6

Quote:
Originally Posted by VoiDeD View Post
Then don't store plugin handles. OnLibraryAdded/Removed will tell you when plugins are loaded and unloaded.
Another problem with that, it requires hardcoded library names when this is for my ff2 rewrite(if you noticed repo name) where it's controlling the subplugins which ultimately one would NEVER know how many subplugins one would get and hardcoding for every subplugin would become giant.

Quote:
Originally Posted by BAILOPAN View Post
The problem you're encountering is basic misunderstanding of C++'s memory model:

PHP Code:
inline void *ftovp(float val)
{
    
float *fp = (float*)&val;
    return (
void*)fp;

You are returning a pointer that immediately becomes invalid memory. I'd be very surprised if the compiler wasn't warning you about this (I strongly suspect GCC or Clang would throw a fit - not sure about VC). The address of &val becomes undefined once the function scope ends.

We discourage writing extensions because they are very complex to write and maintain - and we also discourage using unsafe containers like IBasicTrie. That's not to discourage from using and experimenting with C++, but rather we want released extensions be very high-quality so SourceMod's stability and reliability are not held in question. If you want to release extensions you should use safe containers like ke::HashMap and learn about RAII, pointers, and memory management.
Now that is a better explanation of why to discourage IBasicTrie, but sadly, last time I used CUtlVector and ke::Vector on char* I ended up loosing a char array when the extension got to adding arguements to abilities.
Now about the type-safing, atm, the extension is coding to always get the correct type of keys as I have coded it that way(in a consistency, for args where 1 key can be 3 types, that is covered with another key)

Last edited by WildCard65; 07-18-2014 at 18:36.
WildCard65 is offline
BAILOPAN
Join Date: Jan 2004
Old 07-18-2014 , 18:42   Re: Floats getting lost in IBasicTrie
Reply With Quote #7

Quote:
Originally Posted by WildCard65 View Post
but sadly, last time I used CUtlVector and ke::Vector on char* I ended up loosing a char array when the extension got to adding arguements to abilities.
Now about the type-safing, atm, the extension is coding to always get the correct type of keys as I have coded it that way(in a consistency, for args where 1 key can be 3 types, that is covered with another key)
This isn't a problem with the datastructures - it's with you not understanding C++. Writing unsafe code is not acceptable in our ecosystem so please do not blame the API.
__________________
egg
BAILOPAN is offline
VoiDeD
AlliedModders Donor
Join Date: Mar 2009
Location: Illinois, USA
Old 07-18-2014 , 19:01   Re: Floats getting lost in IBasicTrie
Reply With Quote #8

Quote:
Originally Posted by WildCard65 View Post
Another problem with that, it requires hardcoded library names when this is for my ff2 rewrite(if you noticed repo name) where it's controlling the subplugins which ultimately one would NEVER know how many subplugins one would get and hardcoding for every subplugin would become giant.
Please provide an example use case with regards to FF2 and I'll try to suggest a better implementation that can be done entirely in plugin land with no hardcoding.

Quote:
Originally Posted by WildCard65 View Post
sadly, last time I used CUtlVector and ke::Vector on char* I ended up loosing a char array when the extension got to adding arguements to abilities.
Now about the type-safing, atm, the extension is coding to always get the correct type of keys as I have coded it that way(in a consistency, for args where 1 key can be 3 types, that is covered with another key)
The simple explanation is that you used the APIs incorrectly. What I'm wondering about, however, is why you needed a vector of char*. Were you storing a list of strings?

AMTL has AString and Valve's code has CUtlString for these purposes.
__________________
VoiDeD is offline
WildCard65
Veteran Member
Join Date: Aug 2013
Location: Canada
Old 07-18-2014 , 19:34   Re: Floats getting lost in IBasicTrie
Reply With Quote #9

Quote:
Originally Posted by VoiDeD View Post
Please provide an example use case with regards to FF2 and I'll try to suggest a better implementation that can be done entirely in plugin land with no hardcoding.
You know how FF2 requires subplugins for boss abilities and players can create custom subplugins for new abilities that the standard ff2 subplugins don't provide, but the subplugins are loaded like any other plugin, making it quite difficult for ff2 to tell the difference between a subplugin and a non-subplugin(which is why FF2 1.x.x renames all the files to .ff2 in the freaks folder). But for my rewrite, I want to cut out the usage of "sm plugins load" and "sm plugins unload" but still control when a plugin believes it's loaded(cutting out "OnPluginStart") and make it believe it's unloaded(cutting out "OnPluginEnd") while still having it loaded into memory independent of FF2(as it won't be calling any ff2 natives without FF2 calling it's functions to make it do things). Forwards aren't reliable as OnAllPluginsLoaded from my testing doesn't get recalled when new plugins are loaded late and that's where I want all subplugin info storing to be done, b4 map start to allow for abilities and args to be registered to help with boss parsing. But yet, I want to keep those natives from being called from non-subplugins(for reg abilities and args), which is where Handle storing was needed(but proved to be unreliable, forcing me to use an extension, which has it's benefits of hooking with IPluginListener, allowing me to update the pointer to a subplugin as well as update the info(see my extension's hook for OnPluginLoaded)).

Quote:
Originally Posted by VoiDeD View Post
The simple explanation is that you used the APIs incorrectly. What I'm wondering about, however, is why you needed a vector of char*. Were you storing a list of strings?
For char* vectors, it just makes it easier to use functions expecting const char* and cuts out the use of ".c_str()" which for some reason I forget easily about needing that with strings.

Last edited by WildCard65; 07-18-2014 at 19:36.
WildCard65 is offline
VoiDeD
AlliedModders Donor
Join Date: Mar 2009
Location: Illinois, USA
Old 07-18-2014 , 20:45   Re: Floats getting lost in IBasicTrie
Reply With Quote #10

Quote:
Originally Posted by WildCard65 View Post
You know how FF2 requires subplugins for boss abilities and players can create custom subplugins for new abilities that the standard ff2 subplugins don't provide, but the subplugins are loaded like any other plugin, making it quite difficult for ff2 to tell the difference between a subplugin and a non-subplugin(which is why FF2 1.x.x renames all the files to .ff2 in the freaks folder). But for my rewrite, I want to cut out the usage of "sm plugins load" and "sm plugins unload" but still control when a plugin believes it's loaded(cutting out "OnPluginStart") and make it believe it's unloaded(cutting out "OnPluginEnd") while still having it loaded into memory independent of FF2(as it won't be calling any ff2 natives without FF2 calling it's functions to make it do things). Forwards aren't reliable as OnAllPluginsLoaded from my testing doesn't get recalled when new plugins are loaded late and that's where I want all subplugin info storing to be done, b4 map start to allow for abilities and args to be registered to help with boss parsing. But yet, I want to keep those natives from being called from non-subplugins(for reg abilities and args), which is where Handle storing was needed(but proved to be unreliable, forcing me to use an extension, which has it's benefits of hooking with IPluginListener, allowing me to update the pointer to a subplugin as well as update the info(see my extension's hook for OnPluginLoaded)).
You still haven't described what the actual problem is with making use of the existing plugin system in SM. In the context of the current version of FF2, you can make improvements without any ludicrous plugin management through an extension.

The first thing you need to realize is that FF2 currently has the worst designed system for "subplugins" that has ever existed.

How they should work is this:
1) FF2 shouldn't be loading them. They should be like any other plugin that gets loaded by SM during server load. (i.e.: they should compile to *.smx and simply be in the plugins directory)
2) The current FF2 plugin doesn't (functionally) care about what subplugins are loaded. All the main plugin does is fire forwards into to the subplugins, and the subplugins call natives into the main plugin. This is the proper method for plugins to communicate with each other.

Why does your new version of FF2 need to know which subplugins are loaded? Why does it need to keep plugin handles around?

Quote:
Originally Posted by WildCard65 View Post
For char* vectors, it just makes it easier to use functions expecting const char* and cuts out the use of ".c_str()" which for some reason I forget easily about needing that with strings.
So instead you forget about how to correctly use the container API and introduce subtle memory bugs. Which is worse?
__________________

Last edited by VoiDeD; 07-18-2014 at 20:46.
VoiDeD is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 18:21.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode