On Dec 14, 11:56 am, "RTha...@web.de " <RTha...@web.de wrote:
Hi together,
I am a bit clueless about the following problem:
In the following code excerpt
std::string getStr()
{
std::string bla="asdfsa";
return bla;
}void func1()
{
{
std::string str1=getStr();
}
return;
}str1 is destroyed when the scope inside func1() is left.
Works fine.
But, if getStr() is inside a DLL and is called from func1() in a main
program, this does not work.
At least, I experience that in my code.
Actually, the getStr() is a member function of a class in the DLL which
is exported.
Are they not sharing the same memspace?
Am I missing something?
Contrary to the previous replies to your post, there is something in
this for the comp.lang.c++ community. We encountered a problem
previously which looks very similar to the above problem, and as it
turned out it had a substantial influence on our software design.
In our case, we got a similar message when we unknowingly built our
application (multiple shared libraries/DLL's and some main stubs which
used them) in such a way that each DLL had its own memory heap. We
thought we were using default compiler flags, but as it turned out, we
were not for a DLL arrangement. Under Windows using VC++ (I forget the
version), we got the above behavior, but under linux we had no problems
at all. We temporarily resolved the problem by using appropriate
compiler flags until we found a more robust design solution.
Where this is relevant to the comp.lang.c++ community is that the C++
standard says nothing at all about shared libraries. It talks about
"translatio n units", but that's a different (but related) thing and
doesn't address situations like the above. Indeed, since it does not
prohibit separate memory heaps in DLL's, there's a fair argument which
says it is okay for the compiler implementor to do that. Unfortunately,
this is often not what the programmer expects and can lead to problems
like the one you posted.
There are a few good items in "C++ Coding Standards" by Herb Sutter and
Andrei Alexandrescu which talk about these things (see the "Namespaces
and Modules" section). Item 63 "Use sufficiently portable types in a
module's interface" is particularly relevant, where they discuss
std::string as a function parameter in the module's interface. That
example talks about compiler flags, but the hidden part of std::string
which makes it particularly nasty is that it involves dynamic memory
allocation under the covers. When you force the internal data buffer to
be resized (eg you add characters to the string), memory is allocated
in the module in which that usage of std::string occurred. If you then
pass that string to a different module and it tries to modify it, then
the other module will first try to deallocate the internal buffer and
BAM! there goes your program if your modules are using their own
private memory heaps. If you are returning a std::string by value, then
you essentially have the same problem merely as a result of the
function call mechanics. Which module allocates and deallocates the
memory on each side of the final assignment when the function returns?
Note that all the containers in the STL are vulnerable to this same
gotcha.
If you have to keep the memory heaps separate for some reason (unlikely
from what I can tell from your original post), then there is possibly
still a workaround. You could wrap std::string and make the memory
(re)allocation happen inside your wrapped implementation. Using the
pImpl idiom will suffice to hide this from your compiler so that it
doesn't inline the memory (re)allocation. There is, of course, a
performance penalty for doing this though, so consider carefully if
this matters to you. You should note that this still relies on you
using the same compiler settings and compiler version for all modules
that are going to use your wrapper if you want to have maximum chance
of avoiding inter-module problems (see the book - it contains good
advice on this area).
Hope that helps.
--
Computational Fluid Dynamics, CSIRO (CMIS)
Melbourne, Australia