debugging question



  • what does it tell me when debugging halts at the following code, what should be my steps to find the evildoer:

    void BaseObject::TouchDependenceList(void)
    {
    	C4DOS.Bo->TouchDependenceList(this);
    }
    
    Bool VPBuffer::GetLine(Int32 x, Int32 y, Int32 cnt, void* data, Int32 bitdepth, Bool dithering) const
    {
    	return C4DOS.Sh->VPGetLine(this, x, y, cnt, data, bitdepth, dithering);
    }
    

    Ausnahme ausgelöst bei 0x00007FFF3413A051 (c4dplugin.xdl64) in CINEMA 4D.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x0000000000000000.



  • You're accessing a nullptr value. In VS, open the Call stack while debugging and trace the error message. Usually you quickly find the culprit there.



  • hm, it leads me to a line:

    	op->TouchDependenceList();
    ->	return main;
    

    what api changes could i refer to? since the plugin worked well before adopting to r20.


  • Global Moderator

    Hi ello, thanks for posting here.

    In order to be effective in supporting you, could you please share a larger part of your code?

    With regard to the incriminated line, maybe you can check for pointer validity before calling the TouchDependenceList?

    ...
    if (op != nullptr)
    {
      op->TouchDependenceList();
    }
    ...
    

    Looking forward your comments or code, give best.
    Riccardo



  • thanks for looking into it

    BaseObject *wobbler::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)
    {	  
    	BaseDocument* doc = op->GetDocument();
    	BaseContainer* bc = op->GetDataInstance();
    	ModelingCommandData cd;
    	Bool dirty;
    	Vector *pNormals = NULL;
    	Vector polyNormal = (Vector)0;
    	const CPolygon* pol = NULL;
    	Vector tempVec = (Vector)0;
    
    	Float time = doc->GetTime().GetFrame(doc->GetFps());
    	if ((speed).GetLength()!=0)
    		bc->SetFloat(ZEIT,time);
    	Vector *padr;
    
    	Float arr[12];
    	InitFbm(arr,10,0.1,0.5);
    
    	BaseObject* main = NULL;
    	BaseObject* group = NULL;
    	PolygonObject* clone = NULL;
    	BaseObject* child = NULL;
    
    	BaseContainer cbc;
    
    	if (smooth)
    	{
    		main = BaseObject::Alloc(Osds);
    		main->SetParameter(SDSOBJECT_SUBEDITOR_CM,GeData(subdive),DESCFLAGS_SET::NONE);
    		main->SetParameter(SDSOBJECT_SUBRAY_CM,GeData(subdivr),DESCFLAGS_SET::NONE);
    		group = BaseObject::Alloc(Onull);
    		if (!group) goto Error;
    		group->InsertUnderLast(main);
    	}
    	else
    	{
    		main = BaseObject::Alloc(Onull);
    	}
    	if (!main) goto Error;
    	child = op->GetDown();
    	if (!child) goto Error;
    
    	op->NewDependenceList();
    	while(child)
    	{
    		op->AddDependence(hh,child);
    		child = child->GetNext();
    	}
    
    	dirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS::MATRIX|DIRTYFLAGS::DATA|DIRTYFLAGS::CHILDREN);
    	dirty = dirty || !op->CompareDependenceList();
    
    	if (!dirty) 
    	{
    		blDelete(main);		
    		op->TouchDependenceList();		
    		return op->GetCache(hh);
    	}
    	if (checkEllo()) GePrint("Rebuilding wobbler..."_s);
    	child = op->GetDown();
    
    	while(child)
    	{
    		clone = static_cast<PolygonObject*>(op->GetAndCheckHierarchyClone(hh,child,HIERARCHYCLONEFLAGS::ASPOLY,&dirty,0,false));
    		if (clone)
    		{
    			if (clone->GetType()==Opolygon)
    			{		
    				cd.doc = doc;
    				cd.op = clone;
    				cbc.SetBool(MDATA_SUBDIVIDE_HYPER, true);
    				cbc.SetFloat(MDATA_SUBDIVIDE_ANGLE, 90);
    				cbc.SetInt32(MDATA_SUBDIVIDE_SUB, sub);
    				cd.bc = &cbc;
    				if(SendModelingCommand(MCOMMAND_SUBDIVIDE, cd))
    				{
    					pNormals = GetVertexNormals(clone);
    					padr = clone->GetPointW();
    					pol = clone->GetPolygonR();
    					for (int i=0;i<clone->GetPointCount();i++)
    					{
    						//polyNormal = normalRotation(padr[i], pNormals[i], 0,0,padr,pol,i,false);
    						tempVec = padr[i];
    						Float rmf1 = RidgedMultifractal(arr, Vector(seed + 1) + padr[i]*factor.x + time*speed + op->GetRelPos()*bypos.x, 20, 0, 1)*strength.x;
    						Float rmf2 = RidgedMultifractal(arr, Vector(seed + 2) + padr[i]*factor.y + time*speed + op->GetRelPos()*bypos.y, 20, 0, 1)*strength.y;
    						Float rmf3 = RidgedMultifractal(arr, Vector(seed + 3) + padr[i]*factor.z + time*speed + op->GetRelPos()*bypos.z, 20, 0, 1)*strength.z;
    						tempVec += Vector(rmf1,rmf2,rmf3);
    
    						tempVec += pNormals[i] * Turbulence(Vector(factor.x * (seed + tempVec.x*normalScale)) + time*speed,20,0)*normalStrength;
    						tempVec += pNormals[i] * Turbulence(Vector(factor.y * (seed + tempVec.y*normalScale)) + time*speed,20,0)*normalStrength;
    						tempVec += pNormals[i] * Turbulence(Vector(factor.z * (seed + tempVec.z*normalScale)) + time*speed,20,0)*normalStrength;
    
    						padr[i]=tempVec;
    					}
    					if (pNormals) DeleteMem(pNormals);
    				} 
    				if (smooth)
    					clone->InsertUnderLast(group);
    				else
    					clone->InsertUnderLast(main);
    			}
    			else
    			{
    				blDelete(clone);
    			}
    		}
    		child = child->GetNext();
    	}
    	op->NewDependenceList();
    	child = op->GetDown();
    	while(child)
    	{
    		op->AddDependence(hh,child);
    		child = child->GetNext();
    	}
    
    	if (op != nullptr)
    	{
    		op->TouchDependenceList();
    	}
    	return main;
    
    Error:
    	if (group) blDelete(group);
    	if (main) blDelete(main);
    	return NULL;
    }
    

    edit: still happens



  • what does it mean when the debugger holds at a line like that,

    Vector rndoffset = bc->GetVector(RNDOFFSET);
    

    with a message "CINEMA 4D.exe hat einen Haltepunkt ausgelöst."


  • Global Moderator

    Hi ello, first of all thanks for getting back with the code fragment.

    Analyzing the fragment provided I've ended up in a list of comments:

    • why the "Dependency List" approach is used twice in your code to check children dirty status?

    • why the "Dependency List" approach is used in combination with BaseObject::GetAndCheckHierarchyClone()? In the BaseObject Manual they are properly described and making them working in-cascade can actually lead to unexpected behaviors.

    • most of your code completely lacks pointer validity check; I warmly suggest to extend such a type of check to the whole code snippet to be user that unallocated pointer's methods are not called resulting in a message like "CINEMA 4D.exe hat einen Haltepunkt ausgelöst."

    • what does it mean when the debugger holds at a line like that,
      Vector rndoffset = bc->GetVector(RNDOFFSET);
      with a message "CINEMA 4D.exe hat einen Haltepunkt ausgelöst."

      it simply means that the bc pointer is likely to be invalid.

    Last but not least, considering that in the very net days I'll be pretty busy for the DevKitchen 2018 preparation I can't engage longer discussion or provide thoughtful answers, but back from the event I'll be eager to assist further. One last question: what is the intended delivered functionality of your ObjectData?

    Best, Riccardo



  • thank you Riccardo, i must admit that i just followed the adjustments needed to make it compile under r20. the code worked like that in previous versions and the plugin itself is quite old so i didn't question the code itself.

    maybe it is time to do so and walk thru every line



  • @r_gigante said in debugging question:

    what does it mean when the debugger holds at a line like that,
    Vector rndoffset = bc->GetVector(RNDOFFSET);
    with a message "CINEMA 4D.exe hat einen Haltepunkt ausgelöst."

    it simply means that the bc pointer is likely to be invalid.

    according to this problem, the pointer must be valid, i am checking it like

    	if (!bc) return nullptr;
    

    and if i run the plugin without debugging that one works. additional information, the line before that one throwing the exeption is:

    	Float lightSpeedFactor = bc->GetFloat(LIGHTSPEEDFACTOR);
    

    so, if bc wasn't valid, that one should give the same exception, right?
    so far, i replaced it by

    	Vector rndoffset = Vector(0);// bc->GetVector(RNDOFFSET);
    

    and the whole plugin works. this is really strange


  • Global Moderator

    Hi ello,

    we are back from DevKitchen, but Riccardo is still busy and I just stumbled across this thread.
    Probably he was irritated by the German error message. Actually I think, it's not an exception you are encountering, but just an internal assertion or critical stop, see for example FAQ: Introduction. This could for example happen, if you access a BaseContainer, where you have stored a value with a different type under the same ID before. Maybe RNDOFFSET was used for a different type somewhere lese in the plugin?

    Cheers,
    Andreas


  • Global Moderator

    Thanks Andreas, for jumping in and bumping this conversation up and take my apologize ello for not getting back early.

    Let me know if Andreas suggestion brought some good result or in case, please follow up.

    Riccardo



  • thank you both for getting back. i'll double check again if the ID has been used before. however i am totally lost with this upgrading. since the plugin worked flawless in previous versions and after getting it to compile with r20 it crashes so often.


  • Global Moderator

    Hi ello,
    I'm sure, we will finally get you there. Let's sort it one by one (and if possible one per thread).
    First we'll need to distinguish between actual crashes and above mentioned debug stops. I'd be surprised if a plugin starts really crashing badly and often, just by being converted to and running in R20. Maybe you can take a few screenshots of the debugger's output window in different "crash" situations.
    Bye,
    Andreas



  • finally i found it :) in the init function i used SetFloat... and that caused the problem when trying GetVector

    this part is solved, thanks for pointing me towards the right direction


  • Global Moderator

    @ello said in debugging question:

    when i hover for example RNDOFFSET in visual studio i get enum <unnamed>::RNDOFFSET = 1029

    does this unnamed part cause something?

    No, it doesn't cause anything. It just means the symbol is defined in an unnamed enum. We avoid such nowadays (improved error checking, easier to debug), but they don't do any harm.

    furthermore, since this is a plugin collection the name RNDOFFSET is indeed used with another id in another plugin. does this play a role? i thought that only included files are taken into account?

    Well, I doubt so, but it may. The point is using unique IDs per BaseContainer. And to access a certain ID always with the same type (you could change the type, but let's leave this aside for now). So for a single BaseContainer Is try to make sure and check, that one ID (I mean the symbol or name like RNDOFFSET) is always accessed with the same type, and that no two symbols have identical ID values, so you do not access the same BaseContainer entry with two different names (lets say RNDOFFSET_INT and RNDOFFSET_VEC) but maybe different types.

    here is a screenshot for the actual issue

    From briefly looking at the screenshot on my mobile, it does not give me an additional clue. I recommend to add the debugger console to your layout. Usually we print some extra info there, when we run into a Critical Stop.

    Bye,
    Andreas