Comments (13)
I've found the the problem is not related to the bind of the connection, but only to collection creation, maybe the leak is in the Collection destructor, I can reproduce the leak with the following loop:
for (int i = 1; i < iterations; ++i) {
Connection con = pool->GetConnection();
Statement st(con);
Collection<ostring> lvc(TypeInfo(con, "myarray", TypeInfo::Type));
lvc.Append("T0100101");
}
from ocilib.
Hi,
Do you get the same result if:
- you don't create a connection in each iteration?
- you don't append an element?
from ocilib.
The answer to the first question is YES, to the second question is NO:
This leaks:
for (int i = 1; i < iterations; ++i) {
Collection<ostring> lvc(TypeInfo(con, "myarray", TypeInfo::Type));
lvc.Append("T0100101");
}
This does not:
for (int i = 1; i < iterations; ++i) {
Collection<ostring> lvc(TypeInfo(con, "myarray", TypeInfo::Type));
}
It may be that the optimizer avoid the allocation of "lvc" if not used, but there is a big chance the problem is related to the appended items not freed in the Collection destructor...
from ocilib.
Note also that this leaks too:
TypeInfo ti(con, "myarray", TypeInfo::Type);
for (int i = 1; i < iterations; ++i) {
Collection<ostring> lvc(ti);
lvc.Append("T0100101");
}
PS: Looking at the code I don't see a collection destructor but there is some code I cannot understand at first sight in the constructor that should do the free:
template<class TDataType>
inline Collection<TDataType>::Collection(const TypeInfo &typeInfo)
{
Acquire(Check(OCI_CollCreate(typeInfo)), reinterpret_cast<HandleFreeFunc>(OCI_CollFree), typeInfo.GetConnection().GetHandle());
}
from ocilib.
One question, Is the memory getting freed after Environment::Cleanup() ?
from ocilib.
Actually my tests are done with PS while the binary is running (with a great number of iterations), I tried it also with valgrind adding, Environment::Cleanup() and with a lower number of iterations, these are the results:
100 iterations:
==777== definitely lost: 0 bytes in 0 blocks
==777== indirectly lost: 0 bytes in 0 blocks
==777== possibly lost: 162,104 bytes in 5 blocks
==777== still reachable: 531,911 bytes in 411 blocks
1000 iterations:
==780== definitely lost: 0 bytes in 0 blocks
==780== indirectly lost: 0 bytes in 0 blocks
==780== possibly lost: 162,104 bytes in 5 blocks
==780== still reachable: 531,911 bytes in 411 blocks
5000 iterations:
==824== definitely lost: 0 bytes in 0 blocks
==824== indirectly lost: 0 bytes in 0 blocks
==824== possibly lost: 162,104 bytes in 5 blocks
==824== still reachable: 531,911 bytes in 411 blocks
So it seems that the "variable" amount leaked is freed by the Cleanup() method or it cannot be seen by valgrind. Removing Cleanup() at the end of the program I get (with 100 iterations):
==1251== definitely lost: 0 bytes in 0 blocks
==1251== indirectly lost: 0 bytes in 0 blocks
==1251== possibly lost: 1,000,446 bytes in 156 blocks
==1251== still reachable: 531,912 bytes in 411 blocks
and with 5000:
==1301== definitely lost: 0 bytes in 0 blocks
==1301== indirectly lost: 0 bytes in 0 blocks
==1301== possibly lost: 1,246,926 bytes in 171 blocks
==1301== still reachable: 531,912 bytes in 411 blocks
... so it seems that cleanup is able to free that dangling collections...
from ocilib.
I can add that the bug is probably not in the C++ interface, but also in the C API, this leaks (and I think it should not):
for (int i = 1; i < iterations; ++i) {
OCI_Coll *coll = OCI_CollCreate(ti);
OCI_Elem *elem = OCI_ElemCreate(ti);
OCI_ElemSetString(elem, "T0100101");
OCI_CollAppend(coll, elem);
OCI_ElemFree(elem);
OCI_CollFree(coll);
}
from ocilib.
HI,
OCI is handling a local cache of pinned object (such as collection elements).
I will check if this is OCILIB that does not unpin these objects or the cache itself that decide to not reuse them and allocates new ones.
One question, if you provide an error handler to OCI_Initialize() and then call OCI_Cleanup() after the test, is it fired with a message "Found %d unfreed Object handles" ? I
from ocilib.
Nope, I've build the program using OCI_Initialize() instead of Environment::Initialize(), the program seems to work as before (leaking, and releasing the leak on Cleanup()), but the error handler does not capture nothing... I've added also a cerr after cleanup to be sure that the program reach that point.
For the error handler I used the code from the example in ocilib documentation:
https://vrogier.github.io/ocilib/doc/html/group___ocilib_c_api_error_handling.html
from ocilib.
from ocilib.
create type MYARRAY as table of varchar2(10);
BTW: if it's an oracle internal caching what happens to OCI collections that's not a very smart caching since we had a process constantly growing for this leak that was killed after a month by the OS with an "out of memory" error!
from ocilib.
from ocilib.
Thanks, I compiled with the git version and I can confirm the fix works.
from ocilib.
Related Issues (20)
- Object::Set specialized for Collection of Objects HOT 2
- Compile error under GCC when accessing to an ocilib::Collection item HOT 4
- Using OCIStmtFetch2 HOT 2
- OCI_Execute() raises error OCI-22060 when binding host big_int variables with OCI_BDM_OUT in case the SQL or PL/SQL engine sets a NULL value HOT 10
- OCI_Execute() does not raise exceptions when executing PL/SQL statement raising no data was found PL/SQL exception HOT 4
- String Bind Variables are limited to 64k in size HOT 3
- Pool::GetConnection waits for an infinite time on network failure or disconnection HOT 2
- OCI_GetString() returns NULL for CLOB columns is the CLOB row value was filled with empty_clob() HOT 5
- OCI_BindSetCharsetForm() is not accessible since v4.7.0
- windows vs2019 OCI_ERR_LOADING_SHARED_LIB HOT 7
- OCI_DequeueGet() returns messages with OCI_Object payloads that can have NULL properties while being NOT NULL when queued HOT 6
- I encountered a confusing issue HOT 3
- configure script fails to detect oracle headers path on Oracle Linux 7 HOT 3
- Selecting ADT object hangs when OCILIB initialized with OCI_ENV_THREADED in develop-4.7.5 HOT 2
- Cancel/Terminate/Stop connection request HOT 2
- C++ API: Exception GetMessage HOT 3
- OCI_SubscriptionRegister() generates a segfault on failure HOT 7
- ocilib::Lob::GetConnection() does not compile anymore HOT 7
- OCI_GetTimeout() always returns 0 since v4.7.0 HOT 11
- OCI_GetSqlIdentifier() returns invalid values for Scrollable Statements when called more than once HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ocilib.