[CXX-660] Pointer free early bug Created: 04/Sep/15  Updated: 24/Sep/15  Resolved: 18/Sep/15

Status: Closed
Project: C++ Driver
Component/s: BSON
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: vrqq Assignee: Andrew Morrow (Inactive)
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

See this example below:
bsoncxx::document::view getfilter ()
{
bsoncxx::builder::basic::document filter{};
filter.append( bsoncxx::builder::basic::kvp("p_test", "abcabc") );
return filter.view();
}
main()

{ bsoncxx::document::view filter=getfilter(); //error }

//the filter's construction contain " *_data " pointer. but this pointer's destination memory will free when getfilter() function returned.
so I got "EXC_Bad_ACCESS" error.

This bug occasional occur, I suppose it depends c++ recycling the memory zone with "_data" pointer.

Another source of evidence:
auto filter = th->getfilter();
auto cursor = result.find(filter);
when I run directly, it told me "EXC_Bad_ACCESS".
But when I run into debug mode and "STEP BY STEP" before that statements, it seems normally, and got a right result.

My program is single threaded.



 Comments   
Comment by vrqq [ 24/Sep/15 ]

OK I think I see you point now.
When I want to copy any document::element variable, I should call get_value() to get an copyable version.
Thank you.
Maybe you can rewrite "=" overload method to copy it automatically.

Comment by Andrew Morrow (Inactive) [ 24/Sep/15 ]

The problem is that document::element, which is what view::operator[] returns, is still just a view into the document. To get a value that you can take away, you need to call get_value on the element:

auto _id = tmp.value().view()["_id"].get_value();

Or if you already know that the _id field is of type oid, you could call get_oid directly and get a b_oid value:

auto _id = tmp.value().view()["_id"].get_oid();

Comment by vrqq [ 24/Sep/15 ]

But I still had my doubts.

First I declare a variable _id:
bsoncxx::document::element _id;

Then I pass it a value from a temporary variable.
_id = tmp.value().view()["_id"];

When I execute the statement above, I think it should be "copy" method instead of "reference" method, a new variable "_id" should be CREATED, this two variable should not have any relations.
tmp.value() should be destroyed BUT "_id" not be affected.

In other words, I use bsoncxx::document::element can't declare to a independent variable.
Is that really it? Thank you.

Comment by Andrew Morrow (Inactive) [ 18/Sep/15 ]

I'm closing this issue as I don't believe there is a bug here. Please feel free to re-open it if you need any further help with this issue.

Comment by Andrew Morrow (Inactive) [ 17/Sep/15 ]

I believe the problem, in both instances, is that you are returning a view into an object that has gone out of scope. Taking your second example, you are saying:

tmp.value().view()

Note that the call to 'value()' returns a temporary. Calling 'view' on a temporary gets you a view into the temporary, and then the element returned by accessing _id also refers into a temporary. At the end of the statement, the temporary value is destroyed, and the views are now pointing to free'd memory.

In the first example in your getfilter example you are constructing a document scoped to the function, which owns memory, and then returning a view into it. However, when you leave the function, the document is destroyed, so the view into it is now invalid.

Comment by vrqq [ 05/Sep/15 ]

Another evidence:
main ()
{
bsoncxx::document::element _id;
if (true)

{ auto tmp = dbconn.find_one(filter); _id = tmp.value().view()["_id"]; //debug to watch "_id" is right here. }

bsoncxx::to_json(_id); //It's wrong in here, because when "if statement" done, "tmp" variable is destory, but "_id" variable contain a pointer into "tmp" variable's one location.
}

Generated at Wed Feb 07 21:59:54 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.