简体   繁体   中英

Point of code execution in C++ and shared libraries

A colleague and I were having an interesting discussion about memory allocation when working with shared libraries and "where" code is actually executed.

Hint: I'm explicitly looking for answers in general terms. I know that the following points would work when using the exact same compiler and settings when building the shared library and application. I want to assume that the DLL is built using a completely different compiler than the application.

Given the following struct Foo :

struct Foo
{
    int m_FooBar = 1;

    const char* GetBar()
    {
        return m_Bar.c_str();
    }

    void SetBar(const char* value)
    {
        m_Bar = value;
    }

private:
    std::string m_Bar;
};

Assuming the shared library exposes a function Foo* GetFoo() and an external application calls it:
1.) What happens if the external application calls foo->SetBar("Hello") ?
Would SetBar be executed inside the DLL and thus the memory allocation of m_Bar be safe or would the memory allocation happen inside the external application and thus lead to issues?
2.) What happens if the external application copies the instance pointed to by the returned pointer?
Judging by the many posts out there warning against passing std::string over DLL boundaries I assume that caused by potential different ABIs a default copy could cause problems. Is that correct?
3.) Would it be safe to define custom copy constructors and assignment operators that construct m_Bar by calling .c_str() on the passed instance so that those methods only rely on the API of std::string and not on the ABI?

Hope some C++ gurus can answer some of these questions and shed some light on this topic.

1.) What happens if the external application calls foo->SetBar("Hello")? Would SetBar be executed inside the DLL and thus the memory allocation of m_Bar be safe or would the memory allocation happen inside the external application and thus lead to issues?

There are many problems, not just concerning memory allocations or mixing up C runtime libraries.

For starters, Foo may not even be the same size, std::string definition may be a completely different one, etc. etc. etc.

2.) What happens if the external application copies the instance pointed to by the returned pointer? Judging by the many posts out there warning against passing std::string over DLL boundaries I assume that caused by potential different ABIs a default copy could cause problems. Is that correct?

No need to copy to get into trouble: since you don't know anything about the memory it points to, even using the Foo you were given will break everything.

3.) Would it be safe to define custom copy constructors and assignment operators that construct m_Bar by calling .c_str() on the passed instance so that those methods only rely on the API of std::string and not on the ABI?

Your general idea of trying to go to the lowest level is good. However, trying to play with m_Bar isn't.

Instead, provide a plain C interface and optionally provide wrapper classes in a header. And even then, be careful about allocating/deallocating/using system resources if you are linking with different C runtime libraries (in Windows).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM