digitalmars.D.learn - foreach range construction bug?!!?!?!?
- Phil Lavoie (112/112) Jan 06 2013 Hi all,
- Phil Lavoie (3/3) Jan 06 2013 Oh, BTW, I am aware that GL_EXTENSIONS (whose value is missing
- Era Scarecrow (21/48) Jan 06 2013 but it's actually this: 0x1F03) is not a valid enum for the
- Phil Lavoie (9/9) Jan 06 2013 I am currently working on Windows. The opengl32.lib is an import
- Era Scarecrow (39/41) Jan 06 2013 Mmmm... But no construction happens, empty parameters equals
- Tavi Cacina (5/10) Jan 06 2013 I had once some crashes when calling code in an external dll (on
- Mike Parker (11/27) Jan 07 2013 As a general solution, that's not good advice, but in this case
- Phil Lavoie (7/36) Jan 07 2013 Yeah you're right, though I'm having difficulty making the import
- Phil Lavoie (6/6) Jan 07 2013 I have looked around the a while and I can say that the invalid
- Mike Parker (6/13) Jan 07 2013 If you aren't doing this as a learning exercise, you could save
- Phil Lavoie (5/18) Jan 09 2013 Yeah I kinda am :). Though I am interested in the solution you
Hi all, I am very close to posting a bug report, however I would like some insights first. See the code below: module newstructerror; alias int GLint; alias uint GLenum; enum { GL_EXTENSIONS } /* Errors */ enum { GL_NO_ERROR = 0x0, GL_INVALID_VALUE = 0x0501, GL_INVALID_ENUM = 0x0500, GL_INVALID_OPERATION = 0x0502, GL_STACK_OVERFLOW = 0x0503, GL_STACK_UNDERFLOW = 0x0504, GL_OUT_OF_MEMORY = 0x0505, } version( Defined ) { extern( C ) nothrow { void glGetIntegerv( GLenum p, GLint * v ) { //Do nothing; } GLenum glGetError() { return GL_INVALID_OPERATION; } } } else { pragma( lib, "opengl32.lib" ); extern( C ) nothrow { void glGetIntegerv( GLenum p, GLint * v ); GLenum glGetError(); } } import std.stdio; void main( string[] args ) { GLint noExt = -1; glGetIntegerv( GL_EXTENSIONS, &noExt ); writeln( "Number of extensions: ", noExt ); version( Working ) { //Works with both. auto errors = GLErrors(); foreach( GLenum err; errors ) { writeln( glError( err ) ); } } else { //Crashes in non defined version. foreach( GLenum err; GLErrors() ) { writeln( glError( err ) ); } } } string glError( GLenum errCode ) { switch( errCode ) { case GL_NO_ERROR: return "no error"; case GL_INVALID_VALUE: return "invalid value"; case GL_INVALID_ENUM: return "invalid enum"; case GL_INVALID_OPERATION: return "invalid operation"; case GL_STACK_OVERFLOW: return "stack overflow"; case GL_STACK_UNDERFLOW: return "stack underflow"; case GL_OUT_OF_MEMORY: return "out of memory"; default: return "unknown error"; } } struct GLErrors { private GLenum _current; public: property bool empty() { _current = glGetError(); return ( _current == GL_NO_ERROR ); } property GLenum front() { return _current; } void popFront() { ; } } Now here is what is really troubling me, the non defined version (using the import library) crashes when the range constructor is called inside the foreach statement, which is weird by itself. In addition, in DOES NOT crash when the functions are artifically defined. Anyone seen that before? Or maybe I am doing something wrong? This is the program output when you don't define any versions: Number of extensions: -1 object.Error: Access Violation ---------------- 0x0040DAD8 0x0040D963 0x7799B459 in LdrRemoveLoadAsDataTable 0x7799B42B in LdrRemoveLoadAsDataTable 0x77950133 in KiUserExceptionDispatcher 0x00403A20 0x00403A56 0x00403659 0x00402830 0x751A33AA in BaseThreadInitThunk 0x77979EF2 in RtlInitializeExceptionChain 0x77979EC5 in RtlInitializeExceptionChain ---------------- Defining Working or Defined will produce an infinite loop (or maybe not). Thanks for your time! Phil
Jan 06 2013
Oh, BTW, I am aware that GL_EXTENSIONS (whose value is missing but it's actually this: 0x1F03) is not a valid enum for the request, I am EXPECTING an error from opengl.
Jan 06 2013
On Sunday, 6 January 2013 at 18:59:36 UTC, Phil Lavoie wrote:Hi all, I am very close to posting a bug report, however I would like some insights first. See the code below: version( Working ) { //Works with both. auto errors = GLErrors(); foreach( GLenum err; errors ) { writeln( glError( err ) ); } } else { //Crashes in non defined version. foreach( GLenum err; GLErrors() ) { writeln( glError( err ) ); } }Now here is what is really troubling me, the non defined version (using the import library) crashes when the range constructor is called inside the foreach statement, which is weird by itself. In addition, in DOES NOT crash when the functions are artificially defined. Anyone seen that before? Or maybe I am doing something wrong? This is the program output when you don't define any versions: Number of extensions: -1 object.Error: Access Violation Defining Working or Defined will produce an infinite loop (or maybe not).Oh, BTW, I am aware that GL_EXTENSIONS (whose value is missingbut it's actually this: 0x1F03) is not a valid enum for the request, I am EXPECTING an error from opengl. I doubt it's the constructor, as it just copies it's .init (or zeroizes depending on what's better). The segfault would be from the first call of .empty . Now this is a few shots in the dark and going from memory, but as I recall compiled code (but not linked) won't have any calls actually go where they are suppose to; The linker resolves that during the linking step. So either those addresses aren't getting linked and resolved when it gets compiled, or your opengl32.lib is trying to call something that doesn't exist thereby throwing SegFault. Is the lib compiled with the same compiler (set) as your current source (gdc/gcc for example)? Since it's not a dll (or .so file), perhaps something incompatible is going on in the background. Another thought as I write is are you using gnu/linux? If you are, are you using Xwindows (probably...)? Xwindows as I recall is server/daemon based so if the service(s) aren't running perhaps the openGL driver/service may not even be active, or requires root access to connect to it.
Jan 06 2013
I am currently working on Windows. The opengl32.lib is an import library created using implib /noi /system opengl32.lib C:\Windows\System32\opengl32.dll This all links correctly, otherwise I would get en error during compile + link. I run the command rdmd --force thismodule.d. The library is located on a dev folder which is located in sc.ini. Also, optlink.cfg contains the /scanlib directive. I don't think this is strictly an issue about compilation/link, since moving the constructor away seems to work correctly (-version=Working).
Jan 06 2013
On Sunday, 6 January 2013 at 23:16:13 UTC, Phil Lavoie wrote:since moving the constructor away seems to work correctly (-version=Working).Mmmm... But no construction happens, empty parameters equals default .init. Perhaps it's a bug related to confusing lvalue/rvalue and it's trying to access a temporary variable outside it's scope (so it has garbage data); but even with garbage data... property bool empty() { writeln("Empty!"); _current = glGetError(); return ( _current == GL_NO_ERROR ); } property GLenum front() { writeln("Front!"); return _current; } void popFront() { writeln("PopFront!"); } } If it dies before printing 'Empty!' or 'Front!' then it could be a temporary reference variable bug (I really doubt ctor, although a garbage pointer would cause the problem too). If it dies instead at glGetError it likely is a hidden global variable is getting messed up/not initialized (though seems unlikely). Decompile the assembly code around the foreach loop and the working version, that will give us a definitive explanation of what's really going on. Mmmm I wonder... __traits(compiles) allowed me to see a hidden added 'void* this;' pointer in a union; Perhaps... else { //Crashes in non defined version. assert(__traits(compiles, { foreach( GLenum err; GLErrors() ) { const int a; a++; // breaking on purpose, may show full unrolling // of compiler re-written code writeln( glError( err ) ); } })); }
Jan 06 2013
Am 06.01.2013 19:59, schrieb Phil Lavoie:Now here is what is really troubling me, the non defined version (using the import library) crashes when the range constructor is called inside the foreach statement, which is weird by itself. In addition, in DOES NOT crash when the functions are artifically defined. Anyone seen that before? Or maybe I am doing something wrong?I had once some crashes when calling code in an external dll (on Windows). The problem went away after I've changed the declaration from extern(C) to extern(System). It may be worth trying. Tavi.
Jan 06 2013
On Monday, 7 January 2013 at 07:57:39 UTC, Tavi Cacina wrote:Am 06.01.2013 19:59, schrieb Phil Lavoie:As a general solution, that's not good advice, but in this case it's probably so. The OpenGL functions on Windows are declared with the stdcall calling convention, and as cdecl on other platforms. In D code, that means they need to be declared as extern(Windows) on Windows and extern(C) everywhere else. extern(System) is the convenient way to do that, as the compiler will do the right thing on each platform. Always look at the C headers to understand how the functions are declared before declaring them in D to make sure you've got the correct calling convention.Now here is what is really troubling me, the non defined version (using the import library) crashes when the range constructor is called inside the foreach statement, which is weird by itself. In addition, in DOES NOT crash when the functions are artifically defined. Anyone seen that before? Or maybe I am doing something wrong?I had once some crashes when calling code in an external dll (on Windows). The problem went away after I've changed the declaration from extern(C) to extern(System). It may be worth trying. Tavi.
Jan 07 2013
On Monday, 7 January 2013 at 09:16:00 UTC, Mike Parker wrote:On Monday, 7 January 2013 at 07:57:39 UTC, Tavi Cacina wrote:Yeah you're right, though I'm having difficulty making the import library. implib /noi /system will generate "_name" function names, but extern windows expect them to be "_name someInt". Removing system only seems to remove the prepended "_". Any ideas?Am 06.01.2013 19:59, schrieb Phil Lavoie:As a general solution, that's not good advice, but in this case it's probably so. The OpenGL functions on Windows are declared with the stdcall calling convention, and as cdecl on other platforms. In D code, that means they need to be declared as extern(Windows) on Windows and extern(C) everywhere else. extern(System) is the convenient way to do that, as the compiler will do the right thing on each platform. Always look at the C headers to understand how the functions are declared before declaring them in D to make sure you've got the correct calling convention.Now here is what is really troubling me, the non defined version (using the import library) crashes when the range constructor is called inside the foreach statement, which is weird by itself. In addition, in DOES NOT crash when the functions are artifically defined. Anyone seen that before? Or maybe I am doing something wrong?I had once some crashes when calling code in an external dll (on Windows). The problem went away after I've changed the declaration from extern(C) to extern(System). It may be worth trying. Tavi.
Jan 07 2013
I have looked around the a while and I can say that the invalid calling convention is the most probable cause, though I am still wondering what is the best way to create en import library from a .dll that will export symbols matching to extern( Windows ) "_... int". Implib from digital mars does not seem to have that option... so I am looking around, will let you know what happens!
Jan 07 2013
On Monday, 7 January 2013 at 18:11:14 UTC, Phil Lavoie wrote:I have looked around the a while and I can say that the invalid calling convention is the most probable cause, though I am still wondering what is the best way to create en import library from a .dll that will export symbols matching to extern( Windows ) "_... int". Implib from digital mars does not seem to have that option... so I am looking around, will let you know what happens!If you aren't doing this as a learning exercise, you could save yourself a headache and just use Derelict's OpenGL binding[1]. Then you don't have to worry about import libraries or object file formats. Just DerelictGL3.load() and away you go. [1] https://github.com/aldacron/Derelict3/
Jan 07 2013
On Tuesday, 8 January 2013 at 04:49:42 UTC, Mike Parker wrote:On Monday, 7 January 2013 at 18:11:14 UTC, Phil Lavoie wrote:Yeah I kinda am :). Though I am interested in the solution you propose so I might have a look. Thanks! PhilI have looked around the a while and I can say that the invalid calling convention is the most probable cause, though I am still wondering what is the best way to create en import library from a .dll that will export symbols matching to extern( Windows ) "_... int". Implib from digital mars does not seem to have that option... so I am looking around, will let you know what happens!If you aren't doing this as a learning exercise, you could save yourself a headache and just use Derelict's OpenGL binding[1]. Then you don't have to worry about import libraries or object file formats. Just DerelictGL3.load() and away you go. [1] https://github.com/aldacron/Derelict3/
Jan 09 2013