ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RealDWG AcDbDatabase initialization AccessViolationException error

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
muaslam
535 Views, 7 Replies

RealDWG AcDbDatabase initialization AccessViolationException error

Hello,

 

I am facing an error while initializing an instance of AcDbDatabase class. I have tried creating a pointer instance as well but even that fails with the same exception (AccessViolationException)

 

I need to read AcDbDatabaseSummaryInfo using acdbGetSummaryInfo method. That requires database as a parameter. If there's some other method to get SummaryInfo of the file? 

 

void ReadProperties(std::wstring filename)
{
std::wcout << "Starting to read database info" << std::endl;
AcDbDatabase database(Adesk::kFalse);
std::wcout << "empty database cretaed" << std::endl;
std::wcout << L"Method call end" << std::endl;
}

 

Following is the detailed exception,

 

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at AcDbDatabase.{ctor}(AcDbDatabase* , Boolean , Boolean )
at Bentley.RealDwgWrapperDotNet.RDwgExtractor.ReadProperties(basic_string<wchar_t\,std::char_traits<wchar_t>\,std::allocator<wchar_t> >* filename) in C:\Users\umar.aslam\Documents\Visual Studio 2022\Projects\RealDWGWrapper\RealDWGWrapper\RDwgExtractor.cpp:line 81

 

 

Any help in this regard? 

 

Regards,

Umar

7 REPLIES 7
Message 2 of 8
tbrammer
in reply to: muaslam

You should not create an AcDbDatabase object on the stack. Always use new and delete:

 

void ReadProperties(std::wstring filename)
{
  std::wcout << "Starting to read database info" << std::endl;
  AcDbDatabase *database = new AcDbDatabase(Adesk::kFalse);
  std::wcout << "empty database cretaed" << std::endl;
  std::wcout << L"Method call end" << std::endl;
  delete database;
}

 


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

Message 3 of 8
moogalm
in reply to: muaslam

I don't see any reason why db object shouldn't be created on stack.

 

 

int _tmain(int argc, TCHAR* argv[])
{
    acdbSetHostApplicationServices(&gCreatentHostApp);
    acdbValidateSetup(AcLocale(L"en", L"us"));    
    AcDbDatabase db(Adesk::kFalse);
    db.readDwgFile(L"D:\\Temp\\oneRing.dwg");
    acdbHostApplicationServices()->setWorkingDatabase(&db);
    AcDbDatabaseSummaryInfo* info = nullptr;
    acdbGetSummaryInfo(&db, info);
    ACHAR* pPropertyString = NULL;   
    if (info != nullptr) {
        info->getTitle(pPropertyString);       
        std::wcout << L"Title:"<<pPropertyString<< std::endl;
    }
    acdbCleanUp();
    return 0;
}

 

 

  Some more beautification -

 

template<typename ...Args>
void log(Args && ...args)
{
	(std::wcout << ... << args);
}

#define GET_SUMMINFO_STRING(PROPERTY_NAME,strProp) {                                                                    \
      AcDbDatabaseSummaryInfo* pSummaryInfo = nullptr;                                                                   \
    if (!eOkVerify(acdbGetSummaryInfo(acdbHostApplicationServices()->workingDatabase(), pSummaryInfo)))                   \
         return -1;                                                                                                        \
    ACHAR* pPropertyString = nullptr;                                                                                       \
    if (!eOkVerify(pSummaryInfo->get##PROPERTY_NAME(pPropertyString)))                                                       \
         return -1;                                                                                                           \
    if (pPropertyString != nullptr) {                                                                                          \
        strProp = pPropertyString;                                                                                              \
        log(#PROPERTY_NAME,L"-------------------------", strProp, L"\n");                                                        \
        delete pPropertyString;                                                                                                   \
    }                                                                                                                              \
}




int _tmain(int argc, TCHAR* argv[])
{
    acdbSetHostApplicationServices(&gCreatentHostApp);
    acdbValidateSetup(AcLocale(L"en", L"us"));    
    AcDbDatabase db(Adesk::kFalse);
    db.readDwgFile(L"D:\\Temp\\oneRing.dwg");
    acdbHostApplicationServices()->setWorkingDatabase(&db);
    std::wstring strProp;
    GET_SUMMINFO_STRING(Title, strProp);
    GET_SUMMINFO_STRING(Subject, strProp);
    GET_SUMMINFO_STRING(Comments, strProp);
    GET_SUMMINFO_STRING(Author, strProp);
    GET_SUMMINFO_STRING(Keywords, strProp);
    GET_SUMMINFO_STRING(LastSavedBy, strProp);
    GET_SUMMINFO_STRING(RevisionNumber, strProp);
	GET_SUMMINFO_STRING(HyperlinkBase, strProp);    
    acdbCleanUp();
    return 0;
}

 

 

 

moogalm_0-1656345012515.png

 

 

Message 4 of 8
tbrammer
in reply to: muaslam

I can't give you a profound explanation why you shouldn't create an AcDbDatabase on stack.
AcDbDatabase and AcDbObject are both derived from AcHeapOperators. This is what the ARX docs say:

 

"Objects that inherit from AcHeapOperators are guaranteed to be allocated on the AcDb heap. AcHeapOperators resolves memory allocation conflicts for objects in applications that are built with a version of the C runtime library that differs from the one used by AutoCAD's memory manager. "

 

A second argument might be that I haven't ever seen any ARX sample that created an AcDbDatabase on stack.

 

I assume that it leads to problems if you create any AcHeapOperators-derived object on the stack while it's memory is allocated on the AcDb heap. I would suggest that you simply try to use new and delete and see if it helps.


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

Message 5 of 8
moogalm
in reply to: tbrammer

Well, the quote from the ARX doc is true in the past but doesn’t hold good anymore.

I had quick chat with one of Sr architects of AutoCAD what was the rationale behind the doc –

 


@tbrammer wrote:

I can't give you a profound explanation why you shouldn't create an AcDbDatabase on stack.
AcDbDatabase and AcDbObject are both derived from AcHeapOperators. This is what the ARX docs say:

 

"Objects that inherit from AcHeapOperators are guaranteed to be allocated on the AcDb heap. AcHeapOperators resolves memory allocation conflicts for objects in applications that are built with a version of the C runtime library that differs from the one used by AutoCAD's memory manager. "

In the past, we had issues with different compiler (really runtime) versions in ARX apps vs. AutoCAD. Using the AcHeapOperator made sure that allocation and deletion get to the same runtime.

but nowadays, we require that the ARX app is built with the same VC++ release as AutoCAD, so there is no longer any reason at all for that AcHeapOperators.

 

You need to create AcDbObjects on the heap if you want to hand their control over to AutoCAD for proper deallocation - that is, if your created AcDbObject's lifetime extends the lifetime of your stack.

I.E. if you return from your function, but the AcDbObject you created stays alive (for example, if you added it to the current drawing). Then, of course, you need to allocate it on the heap.

but for code like I have given in the post, the AcDb object's lifetime ends with the lifetime of the stack/function. In this case, it is valid and preferable to use the stack.

 

The AcHeapOperator made sure that if you create an AcDb object on the heap, it goes to the right memory pool. But it never was required for the AcDb object to be allocated on the heap. They could always be created on the stack.

And these days (the latest couple of AutoCAD releases), the AcHeapOperator just calls the CRT malloc() function - the same happens for objects that are not derived from AcHeapOperator. So there is no reason any longer for that AcHeapOperator. We just left it in the public API for compatibility reasons.

Message 6 of 8
tbrammer
in reply to: muaslam

Thanks for the explanation, @moogalm. So you say that it is ok to create an AcDbDatabase on the stack?

In fact I tried @muaslam's code in my own RealDWG project and it ran smooth.

 

Do you have other ideas for the exception reported from @muaslam that seems to arise from the AcDbDatabase constructor?

 

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at AcDbDatabase.{ctor}(AcDbDatabase* , Boolean , Boolean )
at Bentley.RealDwgWrapperDotNet.RDwgExtractor.ReadProperties(basic_string<wchar_t\,std::char_traits<wchar_t>\,std::allocator<wchar_t> >* filename) in C:\Users\umar.aslam\Documents\Visual Studio 2022\Projects\RealDWGWrapper\RealDWGWrapper\RDwgExtractor.cpp:line 81

 

We are talking about a RealDWG project here. It looks as if you are using RealDWG for MicroStation.

@muaslam are you developing Bentley.RealDwgWrapperDotNet  yourself or do you use it as 3rd party product? 

Maybe the provider Bentley can support you then.


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

Message 7 of 8
moogalm
in reply to: tbrammer

@tbrammer 

Yes, if you would call new and delete on a given object in the same function, then don't use it at all, creating object on stack is more elegant. 

 

I don't see enough information to comment on the exception, @muaslam if you can provide simple project that would be great to understand.

 

AccessViolationException are imposibble in managed code, this occurs only when a managed code is interacting with unmanaged c++ code, looks like this what is happening at your end.

Message 8 of 8
muaslam
in reply to: moogalm

Indeed I missed setting Host Application Services. And once, I set Host Application Services like done by moogalm, it works fine for me. I have accepted his answer as a solution.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost