BaseSelect::Free() in 2024 - Access violation reading location
-
Good day. This code worked till 2024 in 2023 and early versions. But now in the v.2024 the last line throws exception: Access violation reading location.
I've edited the ->GetWritablePolygonS() as it described on the doc-page about 2024 migration and because the next ->DeselectAll() and ->Select() lines have started to return me an error.
How to correctly use BaseSelect::Free() in new 2024 is not mentioned.
Am I missing something with the adaptation BaseSelect::Free() too?Int closestPolyID = GetDistanceToMesh(joint, static_cast<BaseObject*> (polyObj)).polyId; if (closestPolyID != NOTINDEX) { BaseSelect* polyS = polyObj->GetWritablePolygonS(); polyS->DeselectAll(); polyS->Select(closestPolyID); ModelingCommandData gmcd; gmcd.doc = doc; gmcd.op = static_cast<BaseObject*> (polyObj); //gmcd.bc = &bc; gmcd.mode = MODELINGCOMMANDMODE::POLYGONSELECTION; if (!(SendModelingCommand(MCOMMAND_SELECTCONNECTED, gmcd))) GePrint("MCOMMAND_SELECTCONNECTED FAILED"_s); if (!(SendModelingCommand(MCOMMAND_SELECTINVERSE, gmcd))) GePrint("MCOMMAND_SELECTINVERSE FAILED"_s); //Convert selection from poly to pnt BaseSelect* pointS = polyObj->GetWritablePointS(); pointS->DeselectAll(); BaseContainer bc; bc.SetInt32(MDATA_CONVERTSELECTION_LEFT, 2); bc.SetInt32(MDATA_CONVERTSELECTION_RIGHT, 0); bc.SetBool(MDATA_CONVERTSELECTION_TOLERANT, false); ModelingCommandData cd; cd.doc = doc; cd.op = static_cast<BaseObject*> (polyObj); cd.bc = &bc; if (!SendModelingCommand(MCOMMAND_CONVERTSELECTION, cd)) GePrint("MCOMMAND_CONVERTSELECTION FAILED"_s); AtomArray::Free(gmcd.result); BaseSelect::Free(polyS); }
-
Hello @yaya,
Thank you for reaching out to us. The code you show here would have been faulty even before 2024. You call
BaseSelect::Free
onpolyS
which is the selected polygons selection ofpolyObj
. When you look into the documentation of GetWritablePolygonS or its legacy variant GetPolygonS, they both will tell you:The selection of visible polygons. The Polygon object owns the pointed base select.
In 2023.2 this would have compiled and run, but you could/would have run into crashes when something was trying to access the selected polygons (without reallocating the selection before). In 2024, Cinema 4D is now more verbose about such things because things such as
BaseSelect
are now copy-on-write, i.e., the actual data is managed by a StrongCowRef in the backend.Hence your access violation. But when you did this before 2024, this was already an access violation, just not a formalized one. The solution is simple, do not free the base select, you do not own it and do not have to manage it.
Cheers,
Ferdinand -
Hello @ferdinand ,
Actually this code works perfectly in 2023.2. And in r21, 23, 24, 25, 26 too.
Now, in 2024 I've started to get the error above. So I decided to do not Free the base select as you say. But now my plugin starts to work incorrectly.
Here is the video of the comparison:
It is the same code, except BaseSelect::Free(polyS); which is now commented in version for 2024
This line (BaseSelect::Free(polyS);) was really necessary when I worked on it, and it does the stuff.
-
Hello @yaya,
Actually this code works perfectly in 2023.2. And in r21, 23, 24, 25, 26 too.
Without wanting to be rude, but "no, it does not", to quote myself:
In 2023.2 this would have compiled and run, but you could/would have run into crashes when something was trying to access the selected polygons (without reallocating the selection before)
Just because you haven't experienced any crashes does not mean what you do is correct. You do not own this
BaseSelect
and therefore cannot free it, because you risk with that other parts of Cinema 4D causing an access violation when trying to access the shared data you deleted. The documentation is very clear on the ownership, and it is also not very logical to delete the active polygon selection of a polygon object, because it will still need one when you have read or modified its data.So, I decided to do not Free the base select as you say. But now my plugin starts to work incorrectly. This line (BaseSelect::Free(polyS);) was really necessary when I worked on it, and it does the stuff.
If you would own this
BaseSelect
, the only thing that would happen by not freeing it, is that you would produce a memory leak, i.e., occupy a spot in memory indefinitely until Cinema 4D closes. That is of course bad, but not a cause for your plugin not working. And now that I am looking more closely at your code, you also should not callAtomArray::Free(gmcd.result);
either because these atoms are owned by whatever document you ran yourSendModelingCommand
in.I am not questioning that you experience problems updating your plugin, and I am happy to help, but we won't get anywhere when you question the basics of object ownership.
Cheers,
Ferdinand -
Hey @ferdinand,
Thanks for your explanation. I understand what you say, and you have a logic, and most of all I am not right and you are, but I just remember that when I putted a lot of efforts to this code, everytime I got an incorrect work of mesh slicing in my plugin. Before I've added this line. Without freeing of BaseSelect it worked like the wrong version on the video above. It was very strange problem, which was looked like a bug, I couldnot understand its root. But when I've added BaseSelect::Free(polyS) it has started to slice my mesh correctly.
Could there be a small, most incredible possibility that this line did something?
-
Hey @yaya,
I do not question that you have problems. I believe you when you say that it 'worked' before. But 'worked' must be in quotation marks because you did violate object ownership. It could even be that this truly was not a concrete issue, because under the hood everything and nothing in our code base that relies on
GetPolygonS
checks first if the data has been irregularly freed before accessing it (I doubt that). Objects at least temporarily not having a selection, could then have caused all sorts of side effects, such as messages not being sent, dirty flags not being set, etc.But this is of course all very speculative since I do not know your plugin code. The code you have posted here is 'harmless', removing the deallocations changes nothing. The core issue is that there are "parts" missing in the 2024 output of your plugin, right? Have you tried flushing
polyS
before leaving the scope, because that is the implicit effect of freeing the selection? I.e., callpolyS->DeselectAll()
? If this is some hairy side effect of you inadvertently muting a message stream because an object suddenly had no selection state anymore, this will be very difficult to debug and fix.edit: It could also have been the opposite, that your plugin relied before on extra update events which were caused by Cinema 4D reinstating the selection you deleted.
Debugging of user code without a concrete subject ("it doesn't work please fix it") is usually out of scope of support, but given the special circumstances of release 2024 you can send us your code and we will have a look. To contact as you can use either our contact form or the mail handle
sdk_support(at)maxon(dot)net
.Cheers,
Ferdinand -
Hello @ferdinand,
Yeah, it will hard to debug, I am agree with you. This problem was strange and hard to debug even in previous versions. I almost blindly found that time that BaseSelect::Free(polyS) somehow has fixed that issue (yeah, I understand how it sounds for you). I just think that two piece of code 2023 and 2024, the second is without BaseSelect::Free(polyS), the second one works wrong, the first one works entirely correctly, despite that this line should do nothing. That's why I assume it should do something behind.
Have you tried flushing polyS before leaving the scope, because that is the implicit effect of freeing the selection? I.e., call polyS->DeselectAll()
My plugin in this module takes the character's mesh and cuts it for parts to make ragdoll's colliders. So each new iteration of -
BaseSelect* polyS = polyObj->GetWritablePolygonS();
-the polyObj is (become) a new mesh.
Before the polyS->DeselectAll(); I change the meshes structure in other parts of code: make cuts, delete polygons, delete points, MCOMMAND_SPLIT, triangulate polys, add new edges etc. Of course ->DeselectAll() too. Then in the piece of code above I grab the resulting mesh and trying to delete isolated islands. But if I do not do the BaseSelect::Free(polyS) before, then I do not get the "Access violation" but in the result "happens something" and it selects not the polygons which should to be deleted... -
Hey @yaya,
okay, and your your plugin hook is
ObjectData
, right? Your plugin is the 'RagDoll' entity, in your screen grab? It is really hard to get here anywhere without code, but here are a few guesses:- Are you 'abusing' your
ObjectData
hook by modifying the scene it is contained in?ObjectData
is bound to the threading restrictions in most of its methods, because most run not on the main thread. This is more relevant than ever with 2024, because more methods have been parallelized. You can modify the scene from anObjectData
plugin, but you must be on the main thread to do it, by for example defer execution to the MT or use a method likeMessage
which often runs on the MT (but I would still avoid doing it when possible). Modyfing the scene means for example inserting, objects, materials, shaders, etc. or adding events. Modifying your cache to your likeing ingetVirtualObjects
is of course okay. - This could also be a nasty side effect of the new data access system.
But these two are of course fairly speculative since I almost know nothing about your plugin. And you said, when I understand you correctly, that you already this problem in the past, and then somehow fixed it by illegally freeing the selection of the object.
I would recommend doing the following things:
- Reduce the complexity of your example scene, that thing is way too complex. Make it as simple as possible by removing as many things as possible with the problem still happening.
- Run
Make Editable
andCurrent State to Object
separately on instances of your faulty plugin output. Analyze the content of the caches to see what is actually happening in the places "where things go wrong". Either you are somehow missing full objects in your cache or skip some data, etc. - Just do normal debugging then: Set a breakpoint on
GetVirtualObjects
in your plugin and step through the code, trying to figure out when you "loose" parts. Avoid skipping 'boring' parts as you easily miss the problem then.
Other than that, I will have to see code, because otherwise there is no magic wand move with which I could guess what is going wrong here for you.
Cheers,
Ferdinand - Are you 'abusing' your