473,387 Members | 1,693 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Returning local variables from DLL

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?

See callstack below

NTDLL! 7c911230()
NTDLL! 7c97cd80()
NTDLL! 7c970af8()
KERNEL32! 7c85e9cf()
_CrtIsValidHeapPointer(const void * 0x009d33d8) line 1697
_free_dbg_lk(void * 0x009d33d8, int 0x00000001) line 1044 + 9 bytes
_free_dbg(void * 0x009d33d8, int 0x00000001) line 1001 + 13 bytes
free(void * 0x009d33d8) line 956 + 11 bytes
operator delete(void * 0x009d33d8) line 7 + 10 bytes
std::allocator<char>::deallocate(void * 0x009d33d8, unsigned int
0x00000021) line 64 + 16 bytes
std::basic_string<char,std::char_traits<char>,std: :allocator<char>
>::_Tidy(unsigned char 0x01) line 592
std::basic_string<char,std::char_traits<char>,std: :allocator<char>
>::~basic_string<char,std::char_traits<char>,std:: allocator<char() line 59 + 17 bytes

Thanks in advance,

--
Regards,

Rainer

Dec 14 '06 #1
6 1843
* RT*****@web.de:
<off-topic>
See the FAQ for information about relevant newsgroups.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Dec 14 '06 #2
<RT*****@web.dewrote in message
news:11**********************@l12g2000cwl.googlegr oups.com...
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?

See callstack below

NTDLL! 7c911230()
NTDLL! 7c97cd80()
NTDLL! 7c970af8()
KERNEL32! 7c85e9cf()
_CrtIsValidHeapPointer(const void * 0x009d33d8) line 1697
_free_dbg_lk(void * 0x009d33d8, int 0x00000001) line 1044 + 9 bytes
_free_dbg(void * 0x009d33d8, int 0x00000001) line 1001 + 13 bytes
free(void * 0x009d33d8) line 956 + 11 bytes
operator delete(void * 0x009d33d8) line 7 + 10 bytes
std::allocator<char>::deallocate(void * 0x009d33d8, unsigned int
0x00000021) line 64 + 16 bytes
std::basic_string<char,std::char_traits<char>,std: :allocator<char>
>>::_Tidy(unsigned char 0x01) line 592
std::basic_string<char,std::char_traits<char>,std: :allocator<char>
>>::~basic_string<char,std::char_traits<char>,std: :allocator<char() line
59 + 17 bytes


Thanks in advance,
DLLs have nothing to do with C++, that's part of the OS and specific
compiler. Try a microsoft newsgroup such as
comp.os.ms-windows-programmer.win32
or others.
Dec 14 '06 #3
On Dec 14, 11:56 am, "RTha...@web.de" <RTha...@web.dewrote:
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
"translation 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

Dec 14 '06 #4

"RT*****@web.de дµÀ£º
"
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;
}
The code is fine.You can prove it by put getStr into yourself's CPP.

Dec 14 '06 #5
On Dec 14, 11:56 am, "RTha...@web.de" <RTha...@web.dewrote:
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
"translation 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).

Hi Craig,

thanks for your kind response. I thought that this had something to do
with C++. Thanks for having a deeper look inside this than the other
replyers.

I hereby forward this thread to comp.os.ms-windows-programmer.win32 to
see if those guys find it appropriate and to know what they think about
it.
I hope I am not making a fault in doing this, but if I do, I'm sure
there's somebody who will teach me good behaviour.

As far as I understand you, even allocating the string in the main
module and passing the pointer to the DLL does not help since a
reallocation (grow, shrink) would cause a crash, right?
Is the underlying memory allocation the same as allocation by new?
new uses the global heap, but as I understand even the global heap is
separated into different memspaces for each module.
Or, to be more concrete, if I allocate an object of a user defined type
with new in the DLL and pass the pointer back to the main module which,
then, deletes the object, would this cause the same behaviour?

--
Regards,

Rainer

Dec 14 '06 #6
As far as I understand you, even allocating the string in the main
module and passing the pointer to the DLL does not help since a
reallocation (grow, shrink) would cause a crash, right?
It *might*, depending on what memory heap management the compiler is
using. You need to check your compiler flags for that.
Is the underlying memory allocation the same as allocation by new?
If that is what the author of your particular STL implementation uses.
The std::string class uses the default allocator<char>, which may or
may not be using the global new operator (I'm not sure if the standard
says anything specific about this particular point). In short, maybe,
so don't depend on it.
new uses the global heap, but as I understand even the global heap is
separated into different memspaces for each module.
Maybe, see earlier comment at the top of this reply.
Or, to be more concrete, if I allocate an object of a user defined type
with new in the DLL and pass the pointer back to the main module which,
then, deletes the object, would this cause the same behaviour?
Yes, this can lead to the same behavior as your first posting. It can
even happen if you are allocating/deallocating built in types, since it
is the actual operator new/delete that is the issue, not the underlying
data type. A data type might implement its own operator new/delete, but
that is a red herring to this issue.

--
Computational Fluid Dynamics, CSIRO (CMIS)
Melbourne, Australia

Dec 15 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Oliver Corona | last post by:
I am wondering if anyone has any insights on the performance benefit (or detriment) of declaring local variables instead of referencing members. Is allocating memory for a new variable more...
8
by: pertheli | last post by:
I am in a situation where only "goto" seems to be the answer for my program logic where I have to retry calling some repeated functions. Can anybody help in the usage of goto and its effect in...
5
by: masood.iqbal | last post by:
My simplistic mind tells me that having local variables within looping constructs is a bad idea. The reason is that these variables are created during the beginning of an iteration and deleted at...
9
by: Stefan Turalski \(stic\) | last post by:
Hi, I done sth like this: for(int i=0; i<10; i++) {...} and after this local declaration of i variable I try to inicialize int i=0;
1
by: bhavin.vyas | last post by:
Friends, I would just like to know that why SQL Server doen't allow us to define a text data type local variable while creating trigger? I tried creating a text variable in a trigger as a...
5
by: Michal Kwiatkowski | last post by:
Hi! I'm building a class that most of methods have similar intro, something like this: def method(self): var_one = self.attr_one var_two = self.attr_two.another_attr empty_list =
55
by: Zytan | last post by:
I see that static is more restricted in C# than in C++. It appears usable only on classes and methods, and data members, but cannot be created within a method itself. Surely this is possible in...
8
by: Samant.Trupti | last post by:
Hi All, I am facing a strange problem.. I am calling a function func2 from func1. Before calling func2 all the local variables in func1 looks fine and has their respective values. When...
3
by: Rene | last post by:
Could someone tell me why is not possible to have Implicitly typed* field level* variables? For example, why won't the following code compile? class Program { var myString = "abc"; static...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.