FIXED: TextDAT with text doesn't output anything to CPlusPlusDAT

I have my CPlusPlusDAT and I noticed a weird behavior, when I start TouchDesigner project with TextDAT directly connected to my CPlusPlusDAT – my CPlusPlusDAT gets empty input event though there’s a text visible in the TextDAT viewer. I verify that by connecting a NullDAT to the TextDAT – NullDAT shows nothing in this case (see the attached screenshot).
The only way I can fix it is to create a new TextDAT and connect it to my CPlusPlusDAT.
Why such behavior might occur?

Weird enough, I think pinpointed the problem: when I don’t call output->setText(""); but pass some non-empty string instead (like, output->setText("n/a"); ) the problem goes away.
Could it be some memory corruption issue elsewhere in the code?..

Actually, the problem persists – now there’s “<n/a>” text in this TextDAT:

I am now able to reproduce the problem. It is indeed, I think, memory corruption. However, I need some help figuring out why the code below is causing it (I suspect something with UTF-8).
I wrote a simple class that demonstrates the error – it is a modification of CPlusPlusDATExample from TouchDesigner samples.
All it does, is sets “errorMessage_” to some string when myExecuteCount == 4 and clears it when it reaches value 5.
On every cook it prints out the input text (“Hello, World!”) and sets same output text (“OUTPUT”). After the error message gets set, the input text becomes “OUTPUT”.
Apparently, getErrorString() corrupts memory when it calls error->setString().
However, I don’t understand why – ASCII is backward compatible with UTF8, right?

I’m on macOS 10.14.5. Haven’t tested Windows platform.

class CPlusPlusDATExample : public DAT_CPlusPlusBase
{
public:
	CPlusPlusDATExample(const OP_NodeInfo* info);
	virtual ~CPlusPlusDATExample();

	virtual void getGeneralInfo(DAT_GeneralInfo*, const OP_Inputs*, void* reserved1) override;
	virtual void execute(DAT_Output*, const OP_Inputs*, void* reserved) override;
    virtual void getErrorString(OP_String *error, void* reserved1) override;
private:
    std::string errorMessage_;
	int32_t	myExecuteCount;
};
CPlusPlusDATExample::CPlusPlusDATExample(const OP_NodeInfo* info)
{
    errorMessage_ = "";
	myExecuteCount = 0;
}

CPlusPlusDATExample::~CPlusPlusDATExample()
{}

void
CPlusPlusDATExample::getGeneralInfo(DAT_GeneralInfo* ginfo, const OP_Inputs* inputs, void* reserved1)
{
	ginfo->cookEveryFrameIfAsked = true;
}

void
CPlusPlusDATExample::getErrorString(OP_String *error, void* reserved1)
{
    if (errorMessage_.size())
        error->setString(errorMessage_.c_str());
}

void
CPlusPlusDATExample::execute(DAT_Output* output,
							const OP_Inputs* inputs,
							void* reserved)
{
	myExecuteCount++;
    
    if (myExecuteCount == 4)
        errorMessage_ = "execute count > 3";
    if (myExecuteCount == 5)
        errorMessage_ = "";

	if (!output)
		return;

	if (inputs->getNumInputs() > 0)
	{
		const OP_DATInput	*cinput = inputs->getInputDAT(0);
        const char* str = cinput->getCell(0, 0);
        std::string p(str);
        if (!p.size())
            std::cout << myExecuteCount << " input is empty" << std::endl;
        else
            std::cout << myExecuteCount << " input is " << p << std::endl;
        
        output->setText("OUTPUT");
	}
	else
	{
        std::cout << myExecuteCount << " NO INPUTS" << std::endl;
	}
}

debug.toe (3.35 KB)

This issue is fixed and will be available on our next official and experimental builds:
2019.19610 +
&
2019.32510+

Thanks for your report!