Skip to content

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

@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

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy