www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Access Violation when accessing Dynamic Array

reply Jack <Jackoz530 gmail.com> writes:
So yeah I've been trying to experiment with the language when I'm 
met with an Access Violation error.

So I've extracted a string from a file and used it as an index 
for a dynamic array. Stripped code sample is :

/////////////////////////////

void foo()
{
string[string] custom;
string keyword;
string script;

File file = File("read.txt", r);
while(!file.eof())
{
script ~= file.readln();
}

foreach(a; script)
{
keyword ~= a; //assuming keyword is "Mario"
}
keyword = stripLeft(keyword);
custom[keyword] = "sample string";

writeln(keyword); // Outputs "Mario"
writeln(custom[keyword]); // Works fine. Outputs "sample string".
writeln(custom["Mario"]); // First-chance exception: 0xc0000005: 
Access violation

}
/////////////////////////////

So am I doing something wrong here? Did I mess with something 
that I shouldn't have?
If it helps I'm using dmd v.2.069.2 on Win7 64-bit.
Jan 02
next sibling parent tsbockman <thomas.bockman gmail.com> writes:
On Saturday, 2 January 2016 at 16:48:41 UTC, Jack wrote:
 So yeah I've been trying to experiment with the language when 
 I'm met with an Access Violation error.

 So I've extracted a string from a file and used it as an index 
 for a dynamic array. Stripped code sample is :

 /////////////////////////////

 void foo()
 {
 string[string] custom;
 string keyword;
 string script;

 File file = File("read.txt", r);
 while(!file.eof())
 {
 script ~= file.readln();
 }

 foreach(a; script)
 {
 keyword ~= a; //assuming keyword is "Mario"
 }
 keyword = stripLeft(keyword);
 custom[keyword] = "sample string";

 writeln(keyword); // Outputs "Mario"
 writeln(custom[keyword]); // Works fine. Outputs "sample 
 string".
 writeln(custom["Mario"]); // First-chance exception: 
 0xc0000005: Access violation

 }
 /////////////////////////////

 So am I doing something wrong here? Did I mess with something 
 that I shouldn't have?
 If it helps I'm using dmd v.2.069.2 on Win7 64-bit.
Your example does not compile, even after I add the required imports (std.algorithm and std.stdio): Error: template std.algorithm.mutation.stripLeft cannot deduce function from argument types !()(string) Please test your example code before asking for help.
Jan 02
prev sibling parent reply tsbockman <thomas.bockman gmail.com> writes:
On Saturday, 2 January 2016 at 16:48:41 UTC, Jack wrote:
 [...]
Also, your sample reads from an external file, "read.txt". Either give us the contents of that file, or change the sample so that it is not required.
Jan 02
parent reply Jack <Jackoz530 gmail.com> writes:
On Saturday, 2 January 2016 at 17:15:53 UTC, tsbockman wrote:
 On Saturday, 2 January 2016 at 16:48:41 UTC, Jack wrote:
 [...]
Also, your sample reads from an external file, "read.txt". Either give us the contents of that file, or change the sample so that it is not required.
Woops, sorry about that. It's about late midnight around here so I didn't really notice. I can't seem to replicate the problem with the dumbed down example(ironic yes). So I'll just send the whole file if you don't mind: http://dpaste.com/11V5BYA (Line 174-183) The contents of the .txt file is : http://dpaste.com/3FVW5QR I just checked it and it compiles but it does that strange Access Violation error.
Jan 02
next sibling parent reply tsbockman <thomas.bockman gmail.com> writes:
On Saturday, 2 January 2016 at 17:39:42 UTC, Jack wrote:
 So I'll just send the whole file if you don't mind:

 http://dpaste.com/11V5BYA (Line 174-183)

 The contents of the .txt file is :
 http://dpaste.com/3FVW5QR

 I just checked it and it compiles but it does that strange 
 Access Violation error.
By far the most likely explanation for an exception at that location, would be if `custom_keyword` really didn't contain a valid key into the `custom` associative array. So, to check I added this code: writefln("custom_keyword: \"%s\"", custom_keyword); stdout.flush(); // This may be required if you're running the code inside an IDE. readln(); Right before `custom[custom_keyword]`. This printed the following: custom_keyword: "Mario " Notice the extra space at the end. The solution is to use `strip()` rather than `stripLeft()`.
Jan 02
parent Jack <Jackoz530 gmail.com> writes:
On Saturday, 2 January 2016 at 17:56:12 UTC, tsbockman wrote:
 On Saturday, 2 January 2016 at 17:39:42 UTC, Jack wrote:
 [...]
By far the most likely explanation for an exception at that location, would be if `custom_keyword` really didn't contain a valid key into the `custom` associative array. So, to check I added this code: writefln("custom_keyword: \"%s\"", custom_keyword); stdout.flush(); // This may be required if you're running the code inside an IDE. readln(); Right before `custom[custom_keyword]`. This printed the following: custom_keyword: "Mario " Notice the extra space at the end. The solution is to use `strip()` rather than `stripLeft()`.
Thank you! I can't believe I haven't noticed the whitespace. I should stop staying up late at night.
Jan 02
prev sibling parent reply tsbockman <thomas.bockman gmail.com> writes:
On Saturday, 2 January 2016 at 17:39:42 UTC, Jack wrote:
 So I'll just send the whole file if you don't mind:

 http://dpaste.com/11V5BYA (Line 174-183)

 The contents of the .txt file is :
 http://dpaste.com/3FVW5QR
I didn't put a lot of effort into trying to actually understand what you're doing, but a couple of other issues that jumped out at me were: 1) You don't need to use `cmp` to compare strings - this isn't Java :) Just use `==` directly - in D this will compare the strings by value, not reference. (If you actually need to compare by reference, you can use `is` or compare the `.ptr` properties.) 2) `if(some_bool == true)` is redundant - just write `if(some_bool)`. Similarly, `if(some_bool == false)` can be shortened to `if(! some_bool)`. 3) Currently, there is no reason for `flags` to be an associative array; it could be replaced by a simple list of variables: bool keyword = false, initialize = false, gameObject_init = false, movement = false, playMusic = false, playSound = false; This would be *much* faster than doing an associative array lookup for every single character in `script`. 4) The value type for the string[string] fields symbol, symbol_init, and keywords could be changed to custom `enum` types, instead of `string`, which would again be much faster.
Jan 02
parent reply Jack <Jackoz530 gmail.com> writes:
On Saturday, 2 January 2016 at 18:14:24 UTC, tsbockman wrote:
 On Saturday, 2 January 2016 at 17:39:42 UTC, Jack wrote:
 So I'll just send the whole file if you don't mind:

 http://dpaste.com/11V5BYA (Line 174-183)

 The contents of the .txt file is :
 http://dpaste.com/3FVW5QR
I didn't put a lot of effort into trying to actually understand what you're doing, but a couple of other issues that jumped out at me were: 1) You don't need to use `cmp` to compare strings - this isn't Java :) Just use `==` directly - in D this will compare the strings by value, not reference. (If you actually need to compare by reference, you can use `is` or compare the `.ptr` properties.)
I didn't actually knew it works that way because last time I tried using '==' directly it won't compare.
 2) `if(some_bool == true)` is redundant - just write 
 `if(some_bool)`.
 Similarly, `if(some_bool == false)` can be shortened to `if(! 
 some_bool)`.
Yeah I did that in a panic attempt to fix the problem.
 3) Currently, there is no reason for `flags` to be an 
 associative array; it could be replaced by a simple list of 
 variables:

 bool
     keyword = false,
     initialize = false,
     gameObject_init = false,
     movement = false,
     playMusic = false,
     playSound = false;

 This would be *much* faster than doing an associative array 
 lookup for every single character in `script`.
I always thought that associative arrays are much more faster and more clean than this. Thanks I'll keep that in mind
 4) The value type for the string[string] fields symbol, 
 symbol_init, and keywords could be changed to custom `enum` 
 types, instead of `string`, which would again be much faster.
And this is news to me too. I'll keep enums in mind. Overall thank you for your help and advice. I'll seriously keep these in mind.
Jan 02
parent tsbockman <thomas.bockman gmail.com> writes:
On Sunday, 3 January 2016 at 03:41:12 UTC, Jack wrote:
 I didn't actually knew it works that way because last time I 
 tried using '==' directly it won't compare.
Well, there are always many ways that things can go wrong (including compiler bugs), but it SHOULD work, so ask on the forums if it doesn't.
 Yeah I did that in a panic attempt to fix the problem.
Ah yes. I've been there before, myself...
 I always thought that associative arrays are much more faster 
 and more clean than this. Thanks I'll keep that in mind
The associative array itself is quite fast, as long as the data set doesn't have too many hash collisions. But, the lookup as a whole is limited by the speed of the key type's hash code function, and of its comparison function. For, say, an integer, both the hash code and the comparison can be accomplished with about two instructions. Thus, a value_type[int] array would be very fast. However, you are using `string` values as the keys, which means that getting the hash code or doing a comparison involves looping over each character in the `string`. Obviously this is going to be slower. This is not to say it's actually *slow* - don't feel bad about using an associative array with `string` keys if that's really what you need. (And you're likely to need one for *something* since you're writing a parser.) Assuming all the key values (variable names) are known at compile time, using boolean variables directly like I suggested is (nearly) the fastest method possible, because the `string` lookup is done during compilation, and is translated into a simple memory access or register access in the generated assembly code.
 And this is news to me too. I'll keep enums in mind.

 Overall thank you for your help and advice. I'll seriously keep 
 these in mind.
You're welcome.
Jan 03