Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    BaseSelect::Free() in 2024 - Access violation reading location

    Cinema 4D SDK
    2024
    2
    8
    1.2k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Y
      yaya
      last edited by yaya

      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);
              }
      

      https://www.ragdollplugin.com

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @yaya
        last edited by

        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 on polyS which is the selected polygons selection of polyObj. 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

        MAXON SDK Specialist
        developers.maxon.net

        Y 1 Reply Last reply Reply Quote 0
        • Y
          yaya @ferdinand
          last edited by yaya

          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.

          https://www.ragdollplugin.com

          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand @yaya
            last edited by ferdinand

            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 call AtomArray::Free(gmcd.result); either because these atoms are owned by whatever document you ran your SendModelingCommand 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

            MAXON SDK Specialist
            developers.maxon.net

            Y 1 Reply Last reply Reply Quote 0
            • Y
              yaya @ferdinand
              last edited by

              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?

              https://www.ragdollplugin.com

              ferdinandF 1 Reply Last reply Reply Quote 0
              • ferdinandF
                ferdinand @yaya
                last edited by ferdinand

                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., call polyS->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

                MAXON SDK Specialist
                developers.maxon.net

                Y 1 Reply Last reply Reply Quote 0
                • Y
                  yaya @ferdinand
                  last edited by yaya

                  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...

                  https://www.ragdollplugin.com

                  ferdinandF 1 Reply Last reply Reply Quote 0
                  • ferdinandF
                    ferdinand @yaya
                    last edited by

                    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:

                    1. 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 an ObjectData plugin, but you must be on the main thread to do it, by for example defer execution to the MT or use a method like Message 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 in getVirtualObjects is of course okay.
                    2. 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:

                    1. 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.
                    2. Run Make Editable and Current 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.
                    3. 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

                    MAXON SDK Specialist
                    developers.maxon.net

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post