VS 2005+ words of warning



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 11/12/2008 at 21:57, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:    
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Some of the code that I'm working on isn't my own and to my surprise a particular piece of it using the STL std::vector iterator was instantaneous crash fun in VS 2005! If you use any STL std::vector iterators, never ever (ever, ever) use the [] operator!!!!! (ever) It is a direct death sentence, immediate and quick crash death kill death. ;)

    I was forced to use 'vector'.at(index) (in my case node.at(index), for instance, for a std::vector<IvyNode> node array). Worse worked in VC 6 but even [] does not work in VS 2005. Avoid it. Don't use it. Forget about it.

    You have been warned.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/12/2008 at 03:10, xxxxxxxx wrote:

    works fine here!

    Not sure what you mean by using []operator with iterators though. Can you give an example?
    I am actually using iterators so I don´t have to use any operators (except when the iterator references an integer value)! :)



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/12/2008 at 06:10, xxxxxxxx wrote:

    Works fine here too, and I've been using VS2005 since it was in beta. Regarding iterators, if you look at <vector> you can see that vector::at(size_type _Pos)  is actually implemented in VS2005 using an iterator, i.e. (*(begin() + _Pos)), whereas vector::[](size_type _Pos)  is not, i.e.  (*(_Myfirst + _Pos)). As noted in the reference, given an index outside the bounds of the vector, at() throws, while the result from  [] is dependent on whether  _SECURE_SCL is defined as 1 (runtime error) or not (result is undefined). Not knowing the actual scenario, this may all mean nothing, but maybe it can point you in some useful direction...who knows?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/12/2008 at 08:58, xxxxxxxx wrote:

    This is the original code from Thomas Luft's Ivy Generator (which worked in VC++ 6 for testing and Xcode 2 when I ported it to MacOS for him) :

    > for (std::vector<IvyRoot>::iterator root = roots.begin(); root != roots.end(); ++root) \> { \>      for (int g = 0; g < 5; ++g) \>      { \>           for (std::vector<IvyNode>::iterator node = root->nodes.begin(); node != root->nodes.end(); ++node) \>           { \>                Vector3d e; \> \>                for (int i = -5; i <= 5; ++i) \>                { \>                     Vector3d tmpAdhesion; \> \>                     if ((node + i) < root->nodes.begin()) tmpAdhesion = root->nodes.front().adhesionVector; \>                     if ((node + i) >= root->nodes.end()) tmpAdhesion = root->nodes.back().adhesionVector; \>                     if (((node + i) >= root->nodes.begin()) && ((node + i) < root->nodes.end())) tmpAdhesion = (node + i)->adhesionVector; \> \>                     e += tmpAdhesion \* gaussian[i+5]; \>                } \> \>                node->smoothAdhesionVector = e / 56.0f; \>           } \> \>           for (std::vector<IvyNode>::iterator node = root->nodes.begin(); node != root->nodes.end(); ++node) \>           { \>                node->adhesionVector = node->smoothAdhesionVector; \>           } \>      } \> }

    Note the 'node + i' references. These are what immediately crashed with VS2005 build. Also seems that the out-of-bound indices aren't stable for iterators. So, I looked around and decided to go with the [] operator to index into the nodes vector:

    This was the modified code which still crashed:

    > int                    g, i; \> LONG               n; \> Vector               e; \> Vector               tmpAdhesion; \> std::vector<IvyRoot>::iterator root; \> std::vector<IvyNode>::iterator node; \> for (root = roots.begin(); root != roots.end(); ++root) \> { \>      for (g = 0; g != 5; ++g) \>      { \>           for (node = root->nodes.begin(); node != root->nodes.end(); ++node) \>           { \>                n = 0L; \>                e =     Vector(0.0f); \>                for (i = -5; i != 6; ++i) \>                { \>                     // Behavior for these two was discovered to be indeterminate - but no crashing! \>                     if ((root->nodes[n+i]) < root->nodes.begin())          tmpAdhesion =     root->nodes.front().adhesionVector; \>                     else if (root->nodes[n+i] >= root->nodes.end())     tmpAdhesion =     root->nodes.back().adhesionVector; \>                     // This line led to the crashes!! \>                     else                         tmpAdhesion =     (root->nodes[n+i]).adhesionVector; \>                     e +=                         tmpAdhesion \* gaussian[i+5]; \>                } \>                ++n; \>                node->smoothAdhesionVector =     e \* 0.017857142857142857142857142857143f; // divided by 56 \>           } \>           for (node = root->nodes.begin(); node != root->nodes.end(); ++node) \>           { \>                node->adhesionVector =     node->smoothAdhesionVector; \>           } \>      } \> }

    So, I changed it again to this and it works perfectly (?) :

    > int                    g, i; \> LONG               n; \> LONG               ln; \> Vector               e; \> Vector               tmpAdhesion; \> std::vector<IvyRoot>::iterator root; \> std::vector<IvyNode>::iterator node; \> for (root = roots.begin(); root != roots.end(); ++root) \> { \>      ln =     (LONG)root->nodes.size(); \>      for (g = 0; g != 5; ++g) \>      { \>           for (node = root->nodes.begin(); node != root->nodes.end(); ++node) \>           { \>                n =     0L; \>                e =     Vector(0.0f); \>                for (i = -5; i != 6; ++i) \>                { \>                     if ((n+i) < 0L)               tmpAdhesion =     root->nodes.front().adhesionVector; \>                     else if ((n+i) >= ln)     tmpAdhesion =     root->nodes.back().adhesionVector; \>                     // nodes[n+i]=crash : nodes.at(n+i)=no crash \>                     else                         tmpAdhesion =     (root->nodes.at(n+i)).adhesionVector; \>                     e +=                         tmpAdhesion \* gaussian[i+5]; \>                } \>                ++n; \>                node->smoothAdhesionVector =     e \* 0.017857142857142857142857142857143f; // divided by 56 \>           } \>           for (node = root->nodes.begin(); node != root->nodes.end(); ++node) \>           { \>                node->adhesionVector =     node->smoothAdhesionVector; \>           } \>      } \> }



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/12/2008 at 09:09, xxxxxxxx wrote:

    To add after the fact:

    Unfortunately, I don't deal with the C++ STL much at all. I've been developing the R10 version in VC++ 6.0 and just moved the project to VS2005 for the R11 build when I discovered this nastiness. We all know that VC++ 6.0 isn't exactly 'robust' in strictness when it comes to standards. So, I was googling about looking for reasons and alternatives (don't have an STL reference on hand). The [] looked like the answer but I'm gun shy now. :)



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/12/2008 at 09:24, xxxxxxxx wrote:

    std::vector operator [] __ contains debug code that will raise the debug assertion dialog, while at() simply throws. I am going to guess that your project has exception handling disabled, and if so, what may be happening is you are just eating the exception thrown by at() when it is called with an out-of-range index. Such a scenario should happen when you call node.at(n+i) in the first and last five iterations of the for(node...) loop - you are dereferencing pointers in front of and behind the vector.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/12/2008 at 09:39, xxxxxxxx wrote:

    Exception handling is enabled for the build - but I'm not try{}catch{}-ing anything.

    No, nodes.at(n+i), by virtue of the conditionals, should always be a valid index. The first two if()s are checking the index bounds you'll note. I do realize that Thomas is skirting the 'boundaries' of invalid indexing by taking 5 indexes on either side of the current node - thus the reason for me to be just as cautious.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/12/2008 at 09:59, xxxxxxxx wrote:

    Sorry...not seeing the forest for the trees there. :)  Hmm...I'll put it in the IDE to get rid of the word-wrap...



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/12/2008 at 11:10, xxxxxxxx wrote:

    Seems to work fine here either using either method. What do these classes look like? Any tricky copy constructors? I only tested with two classes built to the bare minimum of what's implied.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/12/2008 at 16:25, xxxxxxxx wrote:

    Along the same vein here, not that I expect these structures to take up much memory (even many thousands shouldn't) what do I do about the situation if a root or node addition to the vector fails (not enough memory). I'm very sure that the C4D SDK does not have any exception handling - and fallthrough to it would be bad. Do you just try{}catch{} locally and do your error processing in the catch{}?


Log in to reply