繁体   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