簡體   English   中英

C++ 調用 C++ 庫 function 但執行了錯誤的 ZC1C425268E68385D1AB507F14C7

[英]C++ calling a C++ library function but the wrong function is executed

我正在從我的應用程序中調用庫類的函數,並且正在執行同一 class 中的不同 function。 這是一個非常大的程序,其中 android c# 調用 c++ 函數。 那部分工作正常。 c++ 代碼正在調用動態 (*.so) 庫,但正在執行錯誤的 function。 在 VS2019、Clang 5.0 工具集中工作,用於庫代碼和應用程序代碼。 庫源代碼來自第三方,但由我移植和編譯。 相同的代碼在 windows 中運行良好。 以下是相關代碼的濃縮。

包括庫和應用程序代碼共享的文件內容:

假設指向的項目(即 FileHeader 等)在包含文件中聲明。

namespace nsLibraryNameSpc
{
    class Iitems
    {
    public:
        virtual ~Iitems(void) {};
        virtual  int GetAnItem( int instance, unsigned itemID, char *fieldName ) = 0;
    };  
    class Itable
    {
    public:
        virtual ~Itable(void) {};
        virtual int GetBaseInfo( BaseInfo *pBI ) = 0;
        virtual int GetTablePtr( MainTableContents *pMTC ) = 0;
    };  
    class Imethods
    {
    public:
        virtual ~Imethods(void) {};
        virtual int StartMethod( unsigned methodNumber ) = 0;
        virtual int CancelMethod( unsigned methodNumber ) = 0;
    };  
    class Imyclass : public Iitems, public Itable, Imethods
    {
        public:
        Imyclass( void ) {};
        virtual ~Imyclass(void) {};
        
        virtual void GetFileHeader( FileHeader** pFh ) = 0;
        virtual  int AddFileHeader( const char* fileNm, const FileHeader * pFh ) = 0;
        virtual void *testCall02( void *p1, void *p2 ) = 0;
        virtual void *testCall01( void ) = 0;
    };
}

庫源代碼:

假設類 Iitems、Itable 和 Imethods 中的方法存在於庫中。

假設 LOG(char *fmt,...) 會將字符串記錄到文件中。

我的類.cpp

class MyClass : public Imyclass
{
private:
    FileHeader *pHeader;
    unsigned activeMethod;
    
public:
        MyClass( int instance )
        {
            pHeader = 0;
            activeMethod = 0;
        }       
        virtual ~MyClass() 
        {
            if (pHeader != 0)
                delete pHeader;
        }       
        virtual void GetFileHeader( FileHeader** pFh )
        {
            LOG("Inside GetFileHeader\n");
            if (pFh != 0)
                *pFh = pHeader;
            return;
        }       
        virtual  int AddFileHeader( const char* fileNm, const FileHeader * pFh )
        {       
            LOG("Inside AddFileHeader\n");
            //if the file exists then load the file header else return -1;
            LOG("AddFileHeader calling testCall01\n");
            testCall01();
            LOG("Exiting AddFileHeader\n");
            return 0;       
        }       
        virtual void *testCall01( void ) 
        {
            LOG("Inside testCall01\n");
            return 0;
        }       
        virtual void *testCall02( void *p1, void *p2 )
        {
            LOG("Inside testCall02\n");
            return 0;
        }       
        int GetBaseInfo( BaseInfo *pBI )
        {
            // some work
            return 0;
        }
        int GetTablePtr( MainTableContents *pMTC )
        {
            // some work
            return 0;
        }               
        int StartMethod( unsigned methodNumber )
        {
            // some work
            return 0;
        }
        int CancelMethod( unsigned methodNumber )
        {
            // some work
            return 0;
        }       
        int GetAnItem( int instance, unsigned itemID, char *fieldName )
        {
            // some work
            return 0;
        }
}

static int instCntr = 0;

Imyclass *makeMyClass(void)
{
    Imyclass * pRet = (Imyclass *) new MyClass(++instClass);
    return pRet;
}

Android 應用程序的 C++ 代碼:

int testLibraryCalls(void)
{
    Imyclass *pclass = makeMyClass();
    
    LOG("In testLibraryCalls\n");
    pclass->testCall02( (void*)0, (void*)0 );
    LOG("testCall02 finished\n");
    pclass->testCall01();
    LOG("testCall01 finished\n");
    pclass->GetFileHeader(0);
    LOG("GetFileHeader finished\n");
    AddFileHeader( (void*)0, (void*)0 );
    LOG("AddFileHeader finished\n");
}

日志文件顯示:

In testLibraryCalls
Inside AddFileHeader
AddFileHeader calling testCall01
Inside testCall01
Exiting AddFileHeader
testCall02 finished
Inside testCall02
testCall01 finished
GetFileHeader finished
Inside GetFileHeader
AddFileHeader finished

所以調用 testCall02 就是執行 AddFileHeader,

AddFileHeader 正在正確調用 testCall01(在庫代碼中的同一 class 中)。

從應用程序調用 testCall01 會在庫中執行 testCall02。

從應用程序調用 GetFileHeader 要么不執行,要么調用沒有 LOG 語句的東西。

調用 AddFileHeader 會在庫中執行 GetFileHeader。

我已經驗證這台電腦上只有一個.so 文件,其中列出了 nm output 中列出的違規功能。

對我來說,這看起來像是庫加載器失敗,但我不敢相信。 關於哪里出了問題或如何確定根本原因的任何想法都將非常有用。

==================================================== ==============

更新:我將這個頂級動態庫變成了 static 庫 (*.a) 並將其鏈接到主應用程序。 沒變。 呼叫仍然轉到相同的錯誤功能。 所以運行時鏈接不是問題的一部分。

通過使用語法(來自stackoverflow):

void ( Imyclass::* pHeader)(FileHeader* pFileHeader) = &Imyclass::GetFileHeader;
void* pGetFileHeader = (void*&)pHeader;
LOG("==== %p from virtual GetFileHeader", pGetFileHeader);

int ( Imyclass::* pFunc)(const char *, const FileHeader ) = &Imyclass::AddFileHeader;
void* pAddHeader = (void*&)pFunc;
LOG("==== %p from virtual AddFileHeader", pAddHeader);
// these returned an offset into the class's virtual function table

並在它返回之前將其插入庫的 makeMyClass 並在 makeMyClass 從庫返回到應用程序后插入類似的對,我發現應用程序中的虛擬 function 表關閉了 4 個字節(一個指針)。

事實證明,我在 Iitems class 示例中遺漏了一個虛擬 function。 我忽略了它,因為它位於應用程序中未定義的#ifdef 中。

它是在庫中定義的。

class Iitems
{
public:
    virtual ~Iitems(void) {};
    virtual  int GetAnItem( int instance, unsigned itemID, char *fieldName ) = 0;
#ifdef _DEBUG
    virtual void DisplayString(char* str);
#endif
};  

在應用程序中定義 _DEBUG 解決了這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM