Skip to content

"=" operator issue when copying JSONVar reference to JSONVar #66

Open
@nathanjshaffer

Description

@nathanjshaffer

on C11+ and newer compilers, the = operator does not behave as expected. The code is listed below

#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
JSONVar& JSONVar::operator=(JSONVar&& v)
{
cJSON* tmp;
// swap _json
tmp = _json;
_json = v._json;
v._json = tmp;
// swap parent
tmp = _parent;
_parent = v._parent;
v._parent = tmp;
return *this;
}
#endif

This overload is invoked when a JSONVar is set equal to another JSONVar by reference like so:

JSONVar a const 
char input[] = "{'foo':{'bar': '42'}}";
JSONVar a  = JSON.parse(input);
JSONVar b = a["foo"];
Serial.print("b['foo']: ");
Serial.println(b["foo"]);

result:

b['foo']: null

I see a few things wrong with this:
First, swapping the c_json pointers in the JSONVar container does nothing as the linked list is all stored in the c_json structs. The JSONVar object only is created on the fly when requested via the [] operator, and destroyed when out of scope. See below:

JSONVar JSONVar::operator[](const char* key)
{
  
  Serial.println(key);
  if (!cJSON_IsObject(_json)) {
    replaceJson(cJSON_CreateObject());
  }

  cJSON* json = cJSON_GetObjectItemCaseSensitive(_json, key);

  if (json == NULL) {
    json = cJSON_AddNullToObject(_json, key);
  }
  
  return JSONVar(json, _json);    
}

Second, the intent of the code in the C11+ rvalue = overloaded operator is to swap the two objects instead of copy. Why? This is not the same behavior as in older compilers and is not the same behavior if the = operator is used on a JSONVar object directly without referencing. This is is incredibly confusing to have an object be copied in one situation, but then be swapped in a different situation. In my opinion the = operator should always copy, regardless if an lvalue or rvalue is passed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: codeRelated to content of the project itselftype: imperfectionPerceived defect in any part of project

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions