Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inst->attributes[ ] and inst->NextAttribute( ) behave differently #238

Closed
mpictor opened this issue Jun 12, 2013 · 3 comments · Fixed by #265
Closed

inst->attributes[ ] and inst->NextAttribute( ) behave differently #238

mpictor opened this issue Jun 12, 2013 · 3 comments · Fixed by #265
Milestone

Comments

@mpictor
Copy link
Member

mpictor commented Jun 12, 2013

The first loop prints gibberish, while the second loop works.

        SDAI_Application_instance* inst = //...

        for (int j=0; j<inst->AttributeCount(); j++) {
            STEPattribute attr = inst->attributes[j];
            attr.asStr(value);
            cout << " ATT: " << attr.Name() << "  " << value << endl;
        }
        STEPattribute * attr;
        while(  attr = inst->NextAttribute()  ) {
            attr->asStr( value );
            cout << " ATT: " << attr->Name() << "  " << value << endl;
        }
@brlcad
Copy link
Member

brlcad commented Jun 13, 2013

Possibly because inst->attributes[] has unset/NULL attribute members. The first loop doesn't care and ends up calling the copy constructor on unset/NULL, giving bogus values (easily possible if copy constructor isn't defined properly). I'm guessing the second loop encounters the NULL pointer and aborts all subsequent (potentially non-NULL) attributes.

Combining the best of both, this might detect that situation

for (int j=0; j<inst->AttributeCount(); j++) {
    STEPattribute *attr = inst->attributes[j];
    if (!attr)
        cout << "UNEXPECTED NULL ATTRIBUTE ENCOUNTERED" << endl;
    attr->asStr(value);
    cout << "  ATT: " << attr->Name() << "  " << value << endl;
}

@mpictor
Copy link
Member Author

mpictor commented Jun 13, 2013

I've created an example where the order doesn't matter. However, it doesn't read from a file; that could be why it behaves correctly.

//must be linked with libsdai_AP214E3_2010
#define for_first

#include <sstream>
#include <sc_cf.h>
extern void SchemaInit( class Registry & );
#include <STEPfile.h>
#include <sdai.h>
#include <STEPattribute.h>
#include <ExpDict.h>
#include <Registry.h>
#include <errordesc.h>
#include "sc_version_string.h"

int main( int argc, char * argv[] ) {

    Registry  registry( SchemaInit );
    InstMgr   instance_list;
    STEPfile  sfile( registry, instance_list, "", true );
    std::stringstream str;
//     str << "#2 = APPLICATION_CONTEXT";
    str << "('core data for automotive mechanical design processes');" << std::endl;


    std::string value;

    SDAI_Application_instance* inst = registry.ObjCreate( "APPLICATION_CONTEXT",
        "AUTOMOTIVE_DESIGN" );
    inst->STEPread( 2, 0, &instance_list, str, "AUTOMOTIVE_DESIGN", true, false );
    inst->STEPwrite(cout);

    inst->ResetAttributes(); // NextAttribute() doesn't work correctly otherwise

    STEPattribute * attr, *at, a;
    STEPattributeList sal = inst->attributes;

#ifdef for_first
    for (int j=0; j<inst->AttributeCount(); j++) {
        a = sal[j];
        a.asStr(value);
        cout << " ATT: " << a.Name() << "  " << value << endl;
    }
#endif

    while(  attr = inst->NextAttribute()  ) {
        attr->asStr( value );
        cout << " ATT: " << attr->Name() << "  " << value << endl;
    }

#ifndef for_first
    for (int j=0; j<inst->AttributeCount(); j++) {
        a = sal[j];
        a.asStr(value);
        cout << " ATT: " << a.Name() << "  " << value << endl;
    }
#endif

    return 0;
}

output:

#2=APPLICATION_CONTEXT('core data for automotive mechanical design processes');
 ATT: application  'core data for automotive mechanical design processes'
 ATT: application  'core data for automotive mechanical design processes'

@mpictor
Copy link
Member Author

mpictor commented Jun 15, 2013

I think I found the problem.

#include <sc_cf.h>
extern void SchemaInit( class Registry & );
#include <STEPfile.h>
#include <sdai.h>
#include <STEPattribute.h>
#include <ExpDict.h>
#include <Registry.h>

int main( int argc, char * argv[] ) {
    std::string value = "";
    Registry  registry( SchemaInit );
    InstMgr   instance_list;
    STEPfile  sfile( registry, instance_list, "", true );

    //use test_214.stp or data/ap214e3/s1-c5-214/HEAD.stp
    sfile.ReadExchangeFile( argv[1] );

    SDAI_Application_instance* inst = instance_list.GetSTEPentity(0);
    STEPattribute * at;

    inst->ResetAttributes(); // NextAttribute() doesn't work correctly otherwise
    while(  at = inst->NextAttribute()  ) {
        at->asStr( value );
        cout << "using NextAttribute: " << at->Name() << "  " << value << endl;
    }

    for (int j=0; j<inst->AttributeCount(); j++) {
        STEPattribute * att = &(inst->attributes[j]);
        att->asStr(value);
        cout << "using &(inst->attributes[j]): " << att->Name() << "  " << value << endl;
    }

    //first two work, but this one fails
    for (int j=0; j<inst->AttributeCount(); j++) {
        STEPattribute attr = inst->attributes[j];
        attr.asStr(value);
        cout << "using inst->attributes[j]: " << attr.Name() << "  " << value << endl;
    }

    return 0;
}

The third loop produces garbage unless the STEPattribute copy constructor is changed:

STEPattribute::STEPattribute( const STEPattribute & a )
-    : _derive( 0 ), _redefAttr( 0 ), aDesc( a.aDesc ), refCount( 0 ) {}
+    : _derive( a._derive ), _redefAttr( a._redefAttr ), aDesc( a.aDesc ), refCount( 0 ), ptr( a.ptr ) {}

However, this doesn't copy the contents of ptr - it is now shared between two different STEPattributes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants