Issues with your account? Bug us in the Discord!
Calling all advanced coders
Bekenn
Sinclair's Duck
in Zocalo v2.0
There we go, that "advanced" word ought to make everyone look....
I'm having a problem compiling code that was not (repeat, [i]not[/i]) written by me. This code is built to a static library (.lib) file, and utilizes the std::list class. Specifically, one of the headers has the line [code]#include < list> // *[/code] and an object of that class is used as a member variable for a different class defined in the header.
I'll probably have to clarify that later, but on to the weirdness:
Attempting to build the library works just fine -- provided that you're making a release build. Attempting to make a debug build results in (of all things) a syntax error.
You'd think that the code is either syntactically correct or incorrect; changing the build type shouldn't change that.
But wait, there's more! The syntax error occurs [i]not[/i] within the library I'm trying to build, but [i]within [b]list[/b] itself[/i]. That is, the syntax error shows up on line 864 of the header file needed to use std::list!
And it's just a simple syntax error! No other errors are even reported! And this is a file that comes with the IDE (in this case, Visual Studio .NET).
Given the circumstances, I find it impossible to believe that there's anything wrong with the [b]list[/b] header file, and I've checked the library's code for #if statements involving the _DEBUG or NDEBUG symbols. I've even tried changing the debug build settings to more closely match the retail build settings, and so far nothing's had any effect.
Any ideas?
* Without the space. For some reason, either vBulletin or Firefox doesn't change & l t to < if you just run it together with the word ahead of it.
I'm having a problem compiling code that was not (repeat, [i]not[/i]) written by me. This code is built to a static library (.lib) file, and utilizes the std::list class. Specifically, one of the headers has the line [code]#include < list> // *[/code] and an object of that class is used as a member variable for a different class defined in the header.
I'll probably have to clarify that later, but on to the weirdness:
Attempting to build the library works just fine -- provided that you're making a release build. Attempting to make a debug build results in (of all things) a syntax error.
You'd think that the code is either syntactically correct or incorrect; changing the build type shouldn't change that.
But wait, there's more! The syntax error occurs [i]not[/i] within the library I'm trying to build, but [i]within [b]list[/b] itself[/i]. That is, the syntax error shows up on line 864 of the header file needed to use std::list!
And it's just a simple syntax error! No other errors are even reported! And this is a file that comes with the IDE (in this case, Visual Studio .NET).
Given the circumstances, I find it impossible to believe that there's anything wrong with the [b]list[/b] header file, and I've checked the library's code for #if statements involving the _DEBUG or NDEBUG symbols. I've even tried changing the debug build settings to more closely match the retail build settings, and so far nothing's had any effect.
Any ideas?
* Without the space. For some reason, either vBulletin or Firefox doesn't change & l t to < if you just run it together with the word ahead of it.
Comments
Now on to your main problem: I have also encountered this problem in the past. Unfortunately, I can't remember how I fixed it. :) I shall meditate on it tonight and get back to you next access time.
All you others: don't let that keep you from replying!
Perhaps your memory management is getting out of sync? If one set of code defines memory management routines one way, and another defines them another way, the link and/or compile may get confused.
Release builds generally do much less of this, which would explain the release compile working fine.
I don't know that this is your problem, but it is one of the things I look at in similar circumstances.
-- john :shadow1:
[QUOTE][i]Originally posted by Bekenn [/i]
[B]I'm having a problem... [/B][/QUOTE]
I got lost on the "I'm having a problem..." part...
:p
[code]new ((void *)_Pnode) _Node(_Next, _Prev, _Val);
[/code]
It craps out on one of the opening parentheses in that line.
So, what do I have to change?
I don't remember what it is, but there is a define or something to tell VS not to do that. You may have to set a define in your project settings (with the other defines like _NDEBUG) so it affects everything or set it in a header before including windows.h or something like that. Like I said, I can't remember...
It may also be one of those magical project settings. Which version of VS are you using? I have .net '02 and '03 at work, but no access anymore to VC6.
I'm also not thrilled by the initial void* in there, but it is probably fine. Template and meta-template programming makes me dizzy.
The _Node type needs to have a three argument constructor, but I would have expected a different error than syntax.
Have you tried re-arranging the order of the headers of the library vs. your app?
Are you using pre-compiled headers?
[B]What do you do? RTFM! :D Kidding.[/B][/QUOTE]
Heh. Kidding or not, that's exactly what I spent many hours doing before resorting to actually (gasp) asking for help.
[QUOTE][B]I don't remember what it is, but there is a define or something to tell VS not to do that. You may have to set a define in your project settings (with the other defines like _NDEBUG) so it affects everything or set it in a header before including windows.h or something like that. Like I said, I can't remember... [/B][/QUOTE]
Well, that's something to look for, at least.
[QUOTE][B]It may also be one of those magical project settings. Which version of VS are you using? I have .net '02 and '03 at work, but no access anymore to VC6.[/B][/QUOTE]
VS.Net 2002. Y'know, the version that won't work with 2003's project files (grr).
[QUOTE][B]I'm also not thrilled by the initial void* in there, but it is probably fine. [/B][/QUOTE]
I look at it this way: it's in the header. It's a standard header, and it came with Visual Studio. Therefore, it must be okay.
...Okay, so I'm not actually quite that trusting, so I did some research. Turns out that the syntax associated with the [b]new[/b] operator allows you to pass an argument if you're using an overloaded version of [b]new[/b]. That argument comes before the type name. My guess as to what's happening here is that the [b]_Node[/b] variant of the [b]list[/b] class defines its own [b]new[/b] operator, which has a [b]void *[/b] argument.
Notice that the statement above is completely isolated; it isn't [code]x = new ((void *)_Pnode) _Node(_Next, _Prev, _Val);[/code] but rather just plain [code]new ((void *)_Pnode) _Node(_Next, _Prev, _Val);[/code]
My guess is that the overloaded [b]new[/b] operator uses that parameter to store the location of the new [b]_Node[/b]; hence the name [b]_Pnode[/b].
[QUOTE][B]Template and meta-template programming makes me dizzy.[/B][/QUOTE]
I'm exactly the same way. I hate, hate, hate template classes.
[QUOTE][B]The _Node type needs to have a three argument constructor, but I would have expected a different error than syntax. [/B][/QUOTE]
Yeah, that's exactly what got me. Syntax?? Shouldn't the interface for the [b]new[/b] operator be the same regardless of how it's implemented?
[QUOTE][B]Have you tried re-arranging the order of the headers of the library vs. your app?[/B][/QUOTE]
Yup. No luck so far.
[QUOTE][B]Are you using pre-compiled headers? [/B][/QUOTE]
Yes, but every time I change the build settings, that gets recompiled anyway.
Edit: I just tried changing the runtime library that it uses from multi-threaded debug to multi-threaded. Even that doesn't fix the syntax error, so it has to be something else. I'm at a complete loss here.
[B]John, I think you're on to something; the syntax error occurs in a [b]new[/b] statement. Specifically:
[code]new ((void *)_Pnode) _Node(_Next, _Prev, _Val);
[/code]
It craps out on one of the opening parentheses in that line.
So, what do I have to change? [/B][/QUOTE]
I know this may seem stupid... In java scripting I sometimes have to wrap everything in a new set of parenthesis.
When I look at your code below here...
[code]new ((void *)_Pnode) _Node(_Next, _Prev, _Val);
[/code]
I am tempted to suggest changing it to this:
[code]new (((void *)_Pnode) _Node(_Next, _Prev, _Val));
[/code]
That new call might only be seeing the first set( (void *)_Pnode) and truncating the remainder?
If this is totally stupid then forgive me, it just seems to me that a syntax error might be pointing to some kind of typo like this. I get this a lot in Excel formulas and in JavaScripting...
As to why that won't work:
It changes everything after the [b]new[/b] keyword into a single expression. Something that isn't immediately obvious, given that I only provided one line of code, is that [b]_Pnode[/b] is a variable, whereas [b]_Node[/b] is a class type (with [b]_Next[/b], [b]_Prev[/b], and [b]_Val[/b] being arguments for [b]_Node[/b]'s constructor). The syntax of [b]new[/b] works like this:
[b]new[/b] [i][placement] type-name [new-initializer][/i]
Stuff in brackets is optional.
The [i]placement[/i] element is a spot to put arguments if you make your own version of [b]new[/b].
[i]type-name[/i] is where you specify what kind of thing you're creating.
[i]new-initializer[/i] is a spot where you can put an initial value for whatever you're creating.
In this case, [b]((void *)_Pnode)[/b] is the [i]placement[/i] and [b]_Node(_Next, _Prev, _Val)[/b] is the [i]type-name[/i]. Throwing parentheses around that would make the compiler try to consolidate both items into a single element.
Additionally, if it actually were a problem with syntax, the compiler would complain when trying to make a release build. The code itself is not wrong; it has to be something else.
Anyway, I just did some extensive testing with the build options (I created a new configuration called "test", inheriting all options from "release", and changed the options to match "debug" one by one), and I've discovered that it's a combination of two build options at fault here.
The library fails to build if either or both of the two following conditions are true:
1: The _DEBUG symbol is defined
2: A debug version of the run-time library is selected (multi-threaded debug, single-threaded debug, multi-threaded DLL debug)
Edit: The other thing that gets me is that I can't find any reference to any similar problems on Google. So there can't be anything wrong with the [b]list[/b] header.
[code]#ifndef __FixDelete_h__
#define __FixDelete_h__
#if _MSC_VER > 1000
#pragma once
#endif
/////////////////////////////////////////////////////////////////////////////
// This is 'borrowed' from the CRT to ensure that delete is as we expect. //
// //
// The problem arises when using STL, which appears to me as a bug in its //
// implementation of the global operator delete. The STL implementation //
// (from < new> simply calls free, with no regard to how the block was //
// allocated. Under _DEBUG builds, this causes an assert failure since //
// some blocks are allocated with the _CLIENT_BLOCK flag, and free always //
// checks for the _NORMAL_BLOCK flag. //
// //
// The following code correctly passes that flag to the _free_dbg function //
// so that the assert never fails. The code has been written-out since, by //
// including the STL file < new>, the CRT implementation is hidden from the //
// linker. As far as I know, there is no simple way to ignore the source //
// code implementation (from < new>) and force the linker to use the CRT //
// implementation. //
//
#ifdef _DEBUG //
// Structure definition (abridged) from < crt/src/dbgint.h> //
#ifndef nNoMansLandSize //
#define nNoMansLandSize 4 //
typedef struct _CrtMemBlockHeader //
{ //
struct _CrtMemBlockHeader * pBlockHeaderNext; //
struct _CrtMemBlockHeader * pBlockHeaderPrev; //
char * szFileName; //
int nLine; //
size_t nDataSize; //
int nBlockUse; //
long lRequest; //
unsigned char gap[nNoMansLandSize]; //
} _CrtMemBlockHeader; //
#endif // !nNoMansLandSize //
//
// Function definition (abridged) from < crt/src/dbgdel.cpp> //
inline void __cdecl operator delete(void *pUserData) //
{ //
if (pUserData == NULL) //
return; //
_CrtMemBlockHeader* pHead = (((_CrtMemBlockHeader *)pUserData)-1); //
_free_dbg(pUserData, pHead->nBlockUse); //
} //
#endif // _DEBUG //
//
/////////////////////////////////////////////////////////////////////////////
#endif // !__FixDelete_h__
[/code]
Gotta look into this [b]new[/b] header now....
Edit: the [b]new[/b] header simply seems to confirm my theory that _Pnode is a pointer to the new _Node. I haven't seen anything that cares whether or not it's a debug build.
[B]No worries, Jack. The more ideas I see, the more one of them is likely to be right.
...
Additionally, if it actually were a problem with syntax, the compiler would complain when trying to make a release build. [/B][/QUOTE]
:cool:
Well I knew it was a longshot... :D
It's kinda interesting how some things look the same no matter what programming language someone uses...
I just don't know enough about C to be of any help... ;)
Just out of curiosity, what is "void *", and or what does it do? void everything? or multiply something?
operator vs. wildcard...
Looking at some of the other code above, I also have a question as to why (void *_Pnode) wouldn't work
in place of ((void *)_Pnode) ?
I ask this because of how the end of this line looks in the code above:
inline void __cdecl operator delete[b](void *pUserData) [/b]
void * makes a new pointer of type void (ie, no type). The reason the parantheses are needed in your other point are because it is casting _Pnode to the type void*. Without them, it would be declaring _Pnode as a new void*, which would be a problem both in terms of syntax and the fact that _Pnode already exists. You get messy things like this in a language that is designed to be infinitely flexible like C or C++. That's why infinite flexibility isn't always a good thing. :)
Pointers are variables that tell you where in memory a given value is stored. They are usually used to address large structures, and to allow values to persist across boundaries of scope, when ordinary variables would normally be destroyed or inaccessible.
A lot of people find pointers to be very confusing, and in fact one of Java's selling points is its claim that it has no pointers. (Although, in point of fact, practically everything in Java actually is a pointer -- the language just handles the details behind the scenes, and it's the near-complete lack of non-pointers that vastly simplifies the syntax.)
So, is that muddied up enough for you?
I've much to learn (or in this case, un-learn... :eek: )
:p :D
Well I wish I could help Bekenn...
I owe you, and several others out here on thes forums...
I'll eventually find a way to return the favors...
:)
Btw, you guys forgot to tell to Jack, that pointers are usually used to handle classes (those large structures Bekenn mentioned).
[PJH's reminiscent mode]
Pointers to pointers... ughhhh..... *shivers* Heeeeellpppppp!! Wake me up from this nightmare!!
[/PJH's reminiscent mode]
:eek:
Btw, don't be so surprised if there was an error in some header file. That's known to have happened.
- PJH
[B][PJH's reminiscent mode]
Pointers to pointers... ughhhh..... *shivers* Heeeeellpppppp!! Wake me up from this nightmare!!
[/PJH's reminiscent mode][/B][/QUOTE]
Those were always fun; got to deal with them a lot back when I was still coding a cell phone game.
[QUOTE][B]Btw, don't be so surprised if there was an error in some header file. That's known to have happened.[/B][/QUOTE]
Yeah, but VS.Net 2002 has been out for some time now. If there were a problem with the headers, it would have come to light. I haven't found any instance of anyone having the same problem in all my Google searches to date.
[B]
Yeah, but VS.Net 2002 has been out for some time now. If there were a problem with the headers, it would have come to light. I haven't found any instance of anyone having the same problem in all my Google searches to date. [/B][/QUOTE]
Yeah I suppose so.
- PJH
[B]I like pointers. :) You can [i]write[/i] such amazingly confusing code with them. [/B][/QUOTE]
Agreed!
[QUOTE][B]Still no luck with the problem? Unfortunately my [i]meditation[/i] in a 500 year old zen temple didn't help me think of anything other than "try another STL library" [/B][/QUOTE]
Heh. Nope, no luck; I've put that particular module on the backburner for now. There's lots of other code in this project that needs compiling; lately, I've been having to read up on MIDL for one portion. I hadn't ever come across it before.
In case you're wondering, I'm trying to compile the [url=http://www.freeallegiance.org/]Allegiance[/url] [url=http://dev.alleg.net/]source code[/url] that Microsoft released a while back. There's a whole slew of makefiles scattered throughout the archive that the Allegiance folks recommmend using, but I like having everything arranged neatly in an IDE. (And, no, the makefiles were no help in solving this particular problem.)
This smacks of an include order or independent compile with different options...
I took a quick look and I couldn't find the "don't use the new override" option I spoke of. I'm sorry that I don't have any "real" time to work on it for you. :( (Just ask Biggles about the B5 AI doc) :(
[COLOR=skyblue]Pointers:[/COLOR]
I have some bad news for those of you who dislike pointers. If you want to be a really good C/C++ programmer, you need to master the use of pointers, references, double pointers, pointers as parameters, pointer manipulation and incrementing, etc. There is no [url=http://catb.org/~esr/jargon/html/E/elite.html]'leet[/url] [url=http://catb.org/~esr/jargon/html/W/wizard.html]wizard[/url]ly [url=http://catb.org/~esr/jargon/html/H/heavy-wizardry.html]mojo[/url] without pointer mastery.
The only way to avoid pointers is to stick to C#/Java/[url=www.ruby-lang.org]Ruby[/url]/Lisp/Scheme/Python/PHP/Perl/ and other high-level languages (HLL). There is nothing wrong with that, deveopments speed is [b]much[/b] faster with HLL's, and you can spend your memory on powerful API tricks and constructs rather than remembering the format for sending a function pointer, but low-level, highly optimized systems (rendering pipelines, heavy math/physics systems, databases, etc.) are still and for the forseeable future will be) written in C & C++.
Note: I do personal projects, even graphical ones in Ruby or C#. I care about getting stuff done, not performance; it's not like I'm writing a game engine or something.
[B]... it's not like I'm writing a game engine or something. [/B][/QUOTE]
Well what the hell are you doing all day then?!? :D :p j/k
I can write decent stuff in HTML, JavaScript, PHP, Perl, and Cold Fusion and with MySQL and ODBC databases. Beyond those.. My head hurts...
Oh and give me a C-64, and I can whip up some mean BASIC with pokes and peeks... :p