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

Enum Bug (Careful with Arrays and Enums) [SOLVED]


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
11530
Veteran Member
Join Date: Sep 2011
Location: Underworld
Old 04-08-2012 , 18:11   Enum Bug (Careful with Arrays and Enums) [SOLVED]
Reply With Quote #1

Solved: See second post.

I hope someone can help me with this:

I have an enum which, for the purpose of this post, contains the variables below (for the curious, I use an underscore in the enum's name to solve this compiler problem). Now, the problem is that my boolean variable bAllowImmortality is seemingly being written without any such early assignment. It's value? The handle of the player's timer, hIdleTimer! I am completely confused why this should happen. This is the code:

PHP Code:
enum _:PlayerData
{
    
Handle:hIdleTimer INVALID_HANDLE,
    
bool:bAllowImmortality false
};

new 
g_Players[MAXPLAYERS 1][PlayerData];
new 
bool:g_bEnabled true
My hooked player_spawn event contains the problem. I have commented out the PrintToChat debug lines just so you guys can see the real code easier.

PHP Code:
public Action:Event_PlayerSpawn(Handle:Event, const String:Name[], bool:dontBroadcast
{
    if (
g_bEnabled) {
        new 
client GetClientOfUserId(GetEventInt(Event"userid"));
        
//PrintToChat(client, "Spawn1 - AllowImmortality = %d", g_Players[client][bAllowImmortality]);
        
if (client && client < (MaxClients 1)) {
            if (!
IsFakeClient(client)) {
                
//PrintToChat(client, "Spawn2 - AllowImmortality = %d", g_Players[client][bAllowImmortality]);
                
if ((g_Players[client][hIdleTimer] == INVALID_HANDLE) && (g_Players[client][hIdleTimer] = CreateTimer(g_fIntervalIdleTimerclientTIMER_REPEAT))) {
                    
//PrintToChat(client, "SpawnTimerHandle = %d", g_Players[client][hIdleTimer]);
                   // PrintToChat(client, "Spawn3 - AllowImmortality = %d", g_Players[client][bAllowImmortality]);
                    
...
                }
                
//PrintToChat(client, "Spawn4 - AllowImmortality = %d", g_Players[client][bAllowImmortality]);
                
g_Players[client][bAllowImmortality] = true;
                
//PrintToChat(client, "Spawn5 - AllowImmortality = %d", g_Players[client][bAllowImmortality]);
            
}
        }
    }

The output from the PrintToChat lines:

Code:
Spawn1 - AllowImmortality = 0
Spawn2 - AllowImmortality = 0
SpawnTimerHandle = 45547948
Spawn3 - AllowImmortality = 45547948
Spawn4 - AllowImmortality = 45547948
Spawn5 - AllowImmortality = 1
Thank you to any who can shed light on this thoroughly confusing bug.

Edit: I have confirmed that the problem happens exactly during:

Code:
g_Players[client][hIdleTimer] = CreateTimer(g_fInterval, IdleTimer, client, TIMER_REPEAT);

Last edited by 11530; 08-12-2013 at 23:19.
11530 is offline
11530
Veteran Member
Join Date: Sep 2011
Location: Underworld
Old 04-09-2012 , 00:28   Re: Confusing Bug (Variable randomly being written)
Reply With Quote #2

Solved: It seems this is a problem with hacked enums. One must be careful when using arrays inside of them. Think carefully about the value of each member.

Taking everything out of the enum container seems to fix everything!

Last edited by 11530; 05-17-2012 at 15:07.
11530 is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 04-09-2012 , 02:22  
Reply With Quote #3

The forum is not the place to report bugs, use the bug tracker.

Enum structs are a complete hack anyway and are massively missused.

You're issue is that you're trying to assign values to the enum members, that's not how an enum works.
__________________

Last edited by asherkin; 04-09-2012 at 02:23.
asherkin is offline
11530
Veteran Member
Join Date: Sep 2011
Location: Underworld
Old 04-09-2012 , 12:51   Re: Another Serious Enum Bug (Variables overwritten) [SOLVED]
Reply With Quote #4

Firstly asherkin, this wasn't me posting a bug. The OP was me asking for help with the script since I didn't know a bug existed yet. Don't make assumptions please. This also helps other people who may be having similar problems.

I understand that enums aren't the best way to handle OOP, but why not design some struct usage then? You at least need some way to do this. Besides, variables work fine in enums, so why shouldn't using arrays work by extension?

Last edited by 11530; 04-09-2012 at 12:55.
11530 is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 04-09-2012 , 13:04   Re: Another Serious Enum Bug (Variables overwritten) [SOLVED]
Reply With Quote #5

Think about your code.

An enum = a list of named values, i.e.
Code:
enum AnEnum
{ 
    AnEnum_FirstValue,
    AnEnum_SecondValue,
    AnEnum_ThirdValue,
    AnEnum_FourthValue,
    AnEnum_FifthValue,
};
Now, if you print the values of each, you get:
AnEnum_FirstValue = 0
AnEnum_SecondValue = 1
AnEnum_ThirdValue = 2
AnEnum_FourthValue = 3
AnEnum_FifthValue = 4

This works with arrays because the name of the enum evaluates to the next number that would be assigned to an entry in it (AnEnum = 5),
so if you do
Code:
new AnArray[AnEnum];
you get an array with 5 members, then when you use it as a struct
Code:
AnArray[AnEnum_FourthValue]
is exactly the same as
Code:
AnArray[3]
You can also manually assign the values of individual members in the enum, so:
Code:
enum AnEnum
{ 
    AnEnum_FirstValue = 5,
    AnEnum_SecondValue,
    AnEnum_ThirdValue = 8,
    AnEnum_FourthValue = 8,
    AnEnum_FifthValue = 30,
};
Now, if you print the values of each, you get:
AnEnum_FirstValue = 5
AnEnum_SecondValue = 6
AnEnum_ThirdValue = 8
AnEnum_FourthValue = 8
AnEnum_FifthValue = 30
AnEnum = 31

Which still lets array values work, but leads to people screwing up often (case 1 = https://bugs.alliedmods.net/show_bug.cgi?id=5081, case 2 = this thread)

If you look at what you're doing:
Code:
enum AnEnum
{ 
    Handle:AnEnum_FirstValue = INVALID_HANDLE,
    bool:AnEnum_SecondValue = false,
};
INVALID_HANDLE = 0, so
AnEnum_FirstValue = 0

false = 0, so
AnEnum_SecondValue = 0

Therefore,
Code:
AnArray[AnEnum_FirstValue]
and
Code:
AnArray[AnEnum_SecondValue]
are both
Code:
AnArray[0]
Which is why, boys and girls, your values are being overwritten.
__________________
asherkin is offline
11530
Veteran Member
Join Date: Sep 2011
Location: Underworld
Old 04-09-2012 , 13:24   Re: Another Serious Enum Bug (Variables overwritten) [SOLVED]
Reply With Quote #6

It's good we have people like you to slowly teach us these things. I'd hope that one day, C++ structs would be implemented but I guess that'd remove the whole point of the language being fast.

Thank you for the well detailed explanation.
11530 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 06:53.


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