D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6329 - Out of range exceptions not thrown in certain cases
Summary: Out of range exceptions not thrown in certain cases
Status: RESOLVED DUPLICATE of issue 8563
Alias: None
Product: D
Classification: Unclassified
Component: druntime (show other issues)
Version: D2
Hardware: Other Windows
: P2 regression
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-07-15 16:43 UTC by Andrej Mitrovic
Modified: 2014-08-15 18:15 UTC (History)
6 users (show)

See Also:


Attachments
Error messages (27.76 KB, text/plain)
2011-09-08 09:18 UTC, Andrej Mitrovic
Details

Note You need to log in before you can comment on or make changes to this issue.
Description Andrej Mitrovic 2011-07-15 16:43:59 UTC
import std.stdio;
import std.file;

void main()
{
    foreach (string entry; dirEntries(".", SpanMode.shallow))
    {
        writeln(entry[0..1000]);  // out of range
    }
}

DMD 2.053:
D:\>dmd test.d && test.exe
core.exception.RangeError@test(8): Range violation

DMD 2.054:
D:\>dmd test.d && test.exe
D:\>

Wheres the range error??
Comment 1 Vladimir Panteleev 2011-07-21 16:29:13 UTC
As I posted on the newsgroup:

It sounds like standard crash dialogs are disabled on your system (or the problem somehow manifests differently for you). But the cause is the same.

*** This issue has been marked as a duplicate of issue 6308 ***
Comment 2 Andrej Mitrovic 2011-09-08 09:18:00 UTC
Created attachment 1022 [details]
Error messages

2.055 still prints out excessive error messages.
Comment 3 Andrej Mitrovic 2011-09-08 09:19:09 UTC
(In reply to comment #2)
> Created an attachment (id=1022) [details]
> Error messages
> 
> 2.055 still prints out excessive error messages.

I'm sorry, not "still", this is new behavior.
Comment 4 Vladimir Panteleev 2011-09-08 09:23:06 UTC
It doesn't happen on my machine. Have you updated DMD/Phobos/Druntime properly?
Comment 5 Vladimir Panteleev 2011-09-08 09:24:23 UTC
Never mind, it only happens when you don't use -g.
Comment 6 Andrej Mitrovic 2011-09-08 09:28:29 UTC
Typically I install DMD fresh to make sure I didn't screw something up while updating. I can confirm adding -g removes the access violations.
Comment 7 Andrej Mitrovic 2011-10-12 16:35:00 UTC
Here's more issues, this time the sample tries to write to a file handle that was opened in read-only mode:

import std.stdio;
import std.file;

void main()
{
    foreach (string entry; dirEntries(".", SpanMode.shallow))
    {
        auto file = File(entry, "r");
        
        string[] lines;
        foreach (line; file.byLine)
        {
            lines ~= line.idup;
        }
        
        foreach (line; lines)
        {
            file.writeln("asdf");
        }
    }
}

$ dmd test.d && test.exe

Nothing is outputted. But with -g:

$ dmd -g test.d && test.exe
$ std.exception.ErrnoException@D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(1164):  (No error)

So without the symbolic info I get nothing in stdout. However If I change the sample to this:

import std.stdio;
import std.file;

void main()
{
    foreach (string entry; dirEntries(".", SpanMode.shallow))
    {
        auto file = File(entry, "r");
        file.writeln("asdf");
    }
}

$ dmd test.d && test.exe
object.Error: Access Violation
..

and this error message will loop forever.

But with -g I only get one error message as it should be:
$ dmd -g test.d && test.exe
$ std.exception.ErrnoException@D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(1164):  (No error)

So I'll just have to compile with -g all the time until this gets resolved.
Comment 8 Walter Bright 2012-02-05 00:18:07 UTC
This is a druntime issue.
Comment 9 Walter Bright 2012-03-03 20:21:31 UTC
(In reply to comment #0)
> import std.stdio;
> import std.file;
> void main()
> {
>     foreach (string entry; dirEntries(".", SpanMode.shallow))
>     {
>         writeln(entry[0..1000]);  // out of range
>     }
> }
> DMD 2.053:
> D:\>dmd test.d && test.exe
> core.exception.RangeError@test(8): Range violation
> DMD 2.054:
> D:\>dmd test.d && test.exe
> D:\>
> Wheres the range error??

The range error is 'entry' is a string, and you are slicing it beyond it's end. This is not a bug in the compiler or runtime, it's in your code.
Comment 10 Vladimir Panteleev 2012-03-03 20:26:02 UTC
(In reply to comment #9)
> The range error is 'entry' is a string, and you are slicing it beyond it's end.
> This is not a bug in the compiler or runtime, it's in your code.

You have misunderstood the bug report. The problem is that, to the user, the exception was silently discarded 2.054.

In reality, the range exception results in an uncaught SEH exception. On most machines, it will cause the standard "Program has stopped working" dialog, however Andrej has those dialogs disabled.

With DMD 2.058, it causes a barrage of Access Violation errors. This is a bug, as the correct behavior is to print the stack trace of a RangeError and exit.
Comment 11 Andrej Mitrovic 2012-04-07 13:41:00 UTC
I've run into this issue yet again. And I've noticed something: If I compile with '-g' then I get the exception thrown. Otherwise nothing is thrown and I get back an exit code: -1073741819

Here's an example with Vladimir's AE library:

Use this test.xml file:
<Class file="somefile"></Class>

And this script:

import ae.utils.xml;
import std.path;
import std.file;
import std.stream;
import std.stdio;
  
void main()
{
    foreach (string entry; dirEntries(".", SpanMode.shallow))
    {
        if (entry.extension == ".xml")
        {
            Stream stream = new BufferedFile(entry);
            XmlNode document = new XmlDocument(stream);
            auto node = document.children[0];
            
            writeln(node.attributes["file"]);
            writeln(node.attributes["none"]);
        }
    }
}

Notice that "file" will exist but "none" does not, and this should throw a RangeError.

So if I run 'rdmd -g test.d', I get:
core.exception.RangeError@test(20): Range violation
and a stack trace.

But if I run 'rdmd test.d' (without -g) I get the exit code '-1073741819'. I can't even catch the error by using Throwable, it simply exits the app altogether.

As it stands using dirEntries is completely unreliable for me, and this issue keeps shooting me in the foot because I keep forgetting about it as I innocently use the foreach loop without thinking.

And here's a way to force the range error without using -g:

import ae.utils.xml;
import std.path;
import std.file;
import std.stream;
import std.stdio;
  
void main()
{
    string[] entries;
    foreach (string entry; dirEntries(".", SpanMode.shallow))
    {
        if (entry.extension == ".xml")
        {
            entries ~= entry;
        }
    }
    
    foreach (entry; entries)
    {
        Stream stream = new BufferedFile(entry);
        XmlNode document = new XmlDocument(stream);
        auto node = document.children[0];
        
        writeln(node.attributes["file"]);
        writeln(node.attributes["nonexistent_key"]);
    }        
}

So basically the only safe way of using dirEntries is to save a list of files and then do another foreach loop to process it.

I really hope we get this fixed. :/
Comment 12 Rainer Schuetze 2012-04-13 05:18:24 UTC
Did you notice that the return code -1073741819 is 0xC0000005, which usually means "Access Violation"?

I guess this is happening in the stack trace generation code that is executed when an exception is thrown. This code is expensive, has to deal with non-existing or buggy debug information and is unsafe itself. I recommend disabling it by default.

I usually run this early from a shared static module constructor to disable it (including always loading dbghelp.dll and debug symbols at startup):

extern extern(C) __gshared ModuleInfo D4core3sys7windows10stacktrace12__ModuleInfoZ;

void disableStacktrace()
{
	ModuleInfo* info = &D4core3sys7windows10stacktrace12__ModuleInfoZ;
	*cast(typeof(info.o.ctor)*)(cast(void*)info + 8) = null;
}
Comment 13 SomeDude 2012-05-04 15:01:42 UTC
The problem seems solved with 2.059 Win32.
I can see the errors with or without -g.
Comment 14 SomeDude 2012-06-06 02:43:34 UTC
On 2.059 Windows and Linux 32 bit, the problem seems solved.
However the (No error) message is uninformative.
Comment 15 Andrej Mitrovic 2012-06-06 04:21:49 UTC
(In reply to comment #13)
> The problem seems solved with 2.059 Win32.
> I can see the errors with or without -g.

I don't think it's solved, the dirEntries function was changed between releases so now it doesn't trigger the bug.
Comment 16 Alex Rønne Petersen 2012-07-08 21:55:08 UTC
It may not be solved, but I think that keeping a bug open with no up to date repro is pointless. By all means, let's reopen the bug if a repro is found again, but until then, I think it's reasonable to close this.
Comment 18 Vladimir Panteleev 2014-08-15 18:15:57 UTC
This bug has been fixed last year:
https://github.com/D-Programming-Language/dmd/pull/2286

*** This issue has been marked as a duplicate of issue 8563 ***