This is an automated email from the ASF dual-hosted git repository.

hxd pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 48c5488  [ISSUE-2919] Fix C++ client memory leak bug (#2937)
48c5488 is described below

commit 48c5488195c17b49cdaac0116a4754e0cad702b2
Author: wshao08 <[email protected]>
AuthorDate: Thu Apr 1 14:42:22 2021 +0800

    [ISSUE-2919] Fix C++ client memory leak bug (#2937)
---
 client-cpp/src/main/Session.cpp                   |  30 +-
 client-cpp/src/main/Session.h                     |  27 +-
 example/client-cpp-example/src/SessionExample.cpp | 329 +++++++++++-----------
 3 files changed, 195 insertions(+), 191 deletions(-)

diff --git a/client-cpp/src/main/Session.cpp b/client-cpp/src/main/Session.cpp
index 176af63..dccf784 100644
--- a/client-cpp/src/main/Session.cpp
+++ b/client-cpp/src/main/Session.cpp
@@ -251,13 +251,12 @@ bool SessionDataSet::hasNext()
 }
 
 void SessionDataSet::constructOneRow() {
-    vector<Field*> outFields;
+    vector<Field> outFields;
     int loc = 0;
-    Field* field;
     for (int i = 0; i < columnSize; i++) {
-
+        Field field;
         if (duplicateLocation.find(i) != duplicateLocation.end()) {
-            field = new Field(*outFields[duplicateLocation[i]]);
+            field = outFields[duplicateLocation[i]];
         } else {
             MyStringBuffer *bitmapBuffer = bitmapBuffers[loc].get();
             // another new 8 row, should move the bitmap buffer position to 
next byte
@@ -268,36 +267,36 @@ void SessionDataSet::constructOneRow() {
             if (!isNull(loc, rowsIndex)) {
                 MyStringBuffer *valueBuffer = valueBuffers[loc].get();
                 TSDataType::TSDataType dataType = 
getTSDataTypeFromString(columnTypeDeduplicatedList[loc]);
-                field = new Field(dataType);
+                field.dataType = dataType;
                 switch (dataType) {
                 case TSDataType::BOOLEAN: {
                     bool booleanValue = valueBuffer->getBool();
-                    field->boolV = booleanValue;
+                    field.boolV = booleanValue;
                     break;
                 }
                 case TSDataType::INT32: {
                     int intValue = valueBuffer->getInt();
-                    field->intV = intValue;
+                    field.intV = intValue;
                     break;
                 }
                 case TSDataType::INT64: {
                     int64_t longValue = valueBuffer->getLong();
-                    field->longV = longValue;
+                    field.longV = longValue;
                     break;
                 }
                 case TSDataType::FLOAT: {
                     float floatValue = valueBuffer->getFloat();
-                    field->floatV = floatValue;
+                    field.floatV = floatValue;
                     break;
                 }
                 case TSDataType::DOUBLE: {
                     double doubleValue = valueBuffer->getDouble();
-                    field->doubleV = doubleValue;
+                    field.doubleV = doubleValue;
                     break;
                 }
                 case TSDataType::TEXT: {
                     string stringValue = valueBuffer->getString();
-                    field->stringV = stringValue;
+                    field.stringV = stringValue;
                     break;
                 }
                 default: {
@@ -307,7 +306,7 @@ void SessionDataSet::constructOneRow() {
                 }
                 }
             } else {
-                field = new Field(TSDataType::NULLTYPE);
+                field.dataType = TSDataType::NULLTYPE;
             }
             loc++;
         }
@@ -1125,7 +1124,7 @@ void Session::setTimeZone(string zoneId)
     this->zoneId = zoneId;
 }
 
-SessionDataSet* Session::executeQueryStatement(string sql)
+unique_ptr<SessionDataSet> Session::executeQueryStatement(string sql)
 {
     shared_ptr<TSExecuteStatementReq> req(new TSExecuteStatementReq());
     req->__set_sessionId(sessionId);
@@ -1143,7 +1142,8 @@ SessionDataSet* Session::executeQueryStatement(string sql)
         throw IoTDBConnectionException(e.what());
     }
     shared_ptr<TSQueryDataSet> queryDataSet(new 
TSQueryDataSet(resp->queryDataSet));
-    return new SessionDataSet(sql, resp->columns, resp->dataTypeList, 
resp->queryId, client, sessionId, queryDataSet);
+    return unique_ptr<SessionDataSet>(new SessionDataSet(
+        sql, resp->columns, resp->dataTypeList, resp->queryId, client, 
sessionId, queryDataSet));
 }
 
 void Session::executeNonQueryStatement(string sql)
@@ -1162,4 +1162,4 @@ void Session::executeNonQueryStatement(string sql)
     {
         throw IoTDBConnectionException(e.what());
     }
-}
\ No newline at end of file
+}
diff --git a/client-cpp/src/main/Session.h b/client-cpp/src/main/Session.h
index 45ee51c..4e8aba7 100644
--- a/client-cpp/src/main/Session.h
+++ b/client-cpp/src/main/Session.h
@@ -427,12 +427,12 @@ class RowRecord
 {
 public:
     int64_t timestamp;
-    std::vector<Field*> fields;
+    std::vector<Field> fields;
     RowRecord(int64_t timestamp)
     {
         this->timestamp = timestamp;
     }
-    RowRecord(int64_t timestamp, std::vector<Field*> fields) {
+    RowRecord(int64_t timestamp, std::vector<Field> &fields) {
         this->timestamp = timestamp;
         this->fields = fields;
     }
@@ -440,6 +440,11 @@ public:
     {
         this->timestamp = -1;
     }
+
+    void addField(Field &f) {
+        this->fields.push_back(f);
+    }
+
     std::string toString()
     {
         char buf[111];
@@ -448,40 +453,40 @@ public:
         for (int i = 0; i < fields.size(); i++)
         {
             ret.append("\t");
-            TSDataType::TSDataType dataType = fields[i]->dataType;
+            TSDataType::TSDataType dataType = fields[i].dataType;
             switch (dataType)
             {
                 case TSDataType::BOOLEAN:{
-                    if (fields[i]->boolV) ret.append("true");
+                    if (fields[i].boolV) ret.append("true");
                     else ret.append("false");
                     break;
                 }
                 case TSDataType::INT32:{
                     char buf[111];
-                    sprintf(buf,"%d",fields[i]->intV);
+                    sprintf(buf,"%d",fields[i].intV);
                     ret.append(buf);
                     break;
                 }
                 case TSDataType::INT64: {
                     char buf[111];
-                    sprintf(buf,"%lld",fields[i]->longV);
+                    sprintf(buf,"%lld",fields[i].longV);
                     ret.append(buf);
                     break;
                 }
                 case TSDataType::FLOAT:{
                     char buf[111];
-                    sprintf(buf,"%f",fields[i]->floatV);
+                    sprintf(buf,"%f",fields[i].floatV);
                     ret.append(buf);
                     break;
                 }
                 case TSDataType::DOUBLE:{
                     char buf[111];
-                    sprintf(buf,"%lf",fields[i]->doubleV);
+                    sprintf(buf,"%lf",fields[i].doubleV);
                     ret.append(buf);
                     break;
                 }
                 case TSDataType::TEXT: {
-                    ret.append(fields[i]->stringV);
+                    ret.append(fields[i].stringV);
                     break;
                 }
                 case TSDataType::NULLTYPE:{
@@ -659,6 +664,6 @@ class Session
         void createMultiTimeseries(std::vector<std::string> paths, 
std::vector<TSDataType::TSDataType> dataTypes, 
std::vector<TSEncoding::TSEncoding> encodings, 
std::vector<CompressionType::CompressionType> compressors,
             std::vector<std::map<std::string, std::string>>* propsList, 
std::vector<std::map<std::string, std::string>>* tagsList, 
std::vector<std::map<std::string, std::string>>* attributesList, 
std::vector<std::string>* measurementAliasList);
         bool checkTimeseriesExists(std::string path);
-        SessionDataSet* executeQueryStatement(std::string sql);
+        std::unique_ptr<SessionDataSet> executeQueryStatement(std::string sql);
         void executeNonQueryStatement(std::string sql);
-};
\ No newline at end of file
+};
diff --git a/example/client-cpp-example/src/SessionExample.cpp 
b/example/client-cpp-example/src/SessionExample.cpp
index e39e937..f0c5453 100644
--- a/example/client-cpp-example/src/SessionExample.cpp
+++ b/example/client-cpp-example/src/SessionExample.cpp
@@ -39,203 +39,202 @@ void createTimeseries() {
 
     // create timeseries with tags and attributes
     if (!session->checkTimeseriesExists("root.sg1.d1.s4")) {
-      map<string, string> tags;
-      tags["tag1"] = "v1";
-      map<string, string> attributes;
-      attributes["description"] = "v1";
-      session->createTimeseries("root.sg1.d1.s4", TSDataType::INT64, 
TSEncoding::RLE,
-          CompressionType::SNAPPY, NULL, &tags, &attributes, "temperature");
+        map<string, string> tags;
+        tags["tag1"] = "v1";
+        map<string, string> attributes;
+        attributes["description"] = "v1";
+        session->createTimeseries("root.sg1.d1.s4", TSDataType::INT64, 
TSEncoding::RLE,
+            CompressionType::SNAPPY, NULL, &tags, &attributes, "temperature");
     }
 }
 
 void createMultiTimeseries() {
-  if (!session->checkTimeseriesExists("root.sg1.d2.s1") && 
!session->checkTimeseriesExists("root.sg1.d2.s1")) {
-    vector<string> paths;
-    paths.push_back("root.sg1.d2.s1");
-    paths.push_back("root.sg1.d2.s2");
-    vector<TSDataType::TSDataType> tsDataTypes;
-    tsDataTypes.push_back(TSDataType::INT64);
-    tsDataTypes.push_back(TSDataType::INT64);
-    vector<TSEncoding::TSEncoding> tsEncodings;
-    tsEncodings.push_back(TSEncoding::RLE);
-    tsEncodings.push_back(TSEncoding::RLE);
-    vector<CompressionType::CompressionType> compressionTypes;
-    compressionTypes.push_back(CompressionType::SNAPPY);
-    compressionTypes.push_back(CompressionType::SNAPPY);
-
-    vector<map<string,string>> tagsList;
-    map<string,string> tags;
-    tags["unit"] = "kg";
-    tagsList.push_back(tags);
-    tagsList.push_back(tags);
-
-    vector<map<string,string>> attributesList;
-    map<string,string> attributes;
-    attributes["minValue"] = "1";
-    attributes["maxValue"] = "100";
-    attributesList.push_back(attributes);
-    attributesList.push_back(attributes);
-
-    vector<string> alias;
-    alias.push_back("weight1");
-    alias.push_back("weight2");
-
-    session->createMultiTimeseries(paths, tsDataTypes, tsEncodings, 
compressionTypes, NULL, &tagsList, &attributesList, &alias);
-  }
+    if (!session->checkTimeseriesExists("root.sg1.d2.s1") && 
!session->checkTimeseriesExists("root.sg1.d2.s1")) {
+        vector<string> paths;
+        paths.push_back("root.sg1.d2.s1");
+        paths.push_back("root.sg1.d2.s2");
+        vector<TSDataType::TSDataType> tsDataTypes;
+        tsDataTypes.push_back(TSDataType::INT64);
+        tsDataTypes.push_back(TSDataType::INT64);
+        vector<TSEncoding::TSEncoding> tsEncodings;
+        tsEncodings.push_back(TSEncoding::RLE);
+        tsEncodings.push_back(TSEncoding::RLE);
+        vector<CompressionType::CompressionType> compressionTypes;
+        compressionTypes.push_back(CompressionType::SNAPPY);
+        compressionTypes.push_back(CompressionType::SNAPPY);
+
+        vector<map<string,string>> tagsList;
+        map<string,string> tags;
+        tags["unit"] = "kg";
+        tagsList.push_back(tags);
+        tagsList.push_back(tags);
+
+        vector<map<string,string>> attributesList;
+        map<string,string> attributes;
+        attributes["minValue"] = "1";
+        attributes["maxValue"] = "100";
+        attributesList.push_back(attributes);
+        attributesList.push_back(attributes);
+
+        vector<string> alias;
+        alias.push_back("weight1");
+        alias.push_back("weight2");
+
+        session->createMultiTimeseries(paths, tsDataTypes, tsEncodings, 
compressionTypes, NULL, &tagsList, &attributesList, &alias);
+    }
 }
 
 void insertRecord() {
-  string deviceId = "root.sg1.d1";
-  vector<string> measurements;
-  measurements.push_back("s1");
-  measurements.push_back("s2");
-  measurements.push_back("s3");
-  for (int64_t time = 0; time < 100; time++) {
-    vector<string> values;
-    values.push_back("11");
-    values.push_back("22");
-    values.push_back("33");
-    session->insertRecord(deviceId, time, measurements, values);
-  }
+    string deviceId = "root.sg1.d1";
+    vector<string> measurements;
+    measurements.push_back("s1");
+    measurements.push_back("s2");
+    measurements.push_back("s3");
+    for (int64_t time = 0; time < 100; time++) {
+        vector<string> values;
+        values.push_back("11");
+        values.push_back("22");
+        values.push_back("33");
+        session->insertRecord(deviceId, time, measurements, values);
+    }
 }
 
 void insertTablet() {
-  pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
-  pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
-  pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
-  vector<pair<string, TSDataType::TSDataType>> schemas;
-  schemas.push_back(pairA);
-  schemas.push_back(pairB);
-  schemas.push_back(pairC);
-
-  Tablet tablet("root.sg1.d1", schemas, 100);
-
-  for (int64_t time = 0; time < 100; time++) {
-    int row = tablet.rowSize++;
-    tablet.timestamps[row] = time;
-    for (int i = 0; i < 3; i++) {
-      tablet.values[i][row] = to_string(i);
+    pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
+    pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
+    pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
+    vector<pair<string, TSDataType::TSDataType>> schemas;
+    schemas.push_back(pairA);
+    schemas.push_back(pairB);
+    schemas.push_back(pairC);
+
+    Tablet tablet("root.sg1.d1", schemas, 100);
+
+    for (int64_t time = 0; time < 100; time++) {
+        int row = tablet.rowSize++;
+        tablet.timestamps[row] = time;
+        for (int i = 0; i < 3; i++) {
+            tablet.values[i][row] = to_string(i);
+        }
+        if (tablet.rowSize == tablet.maxRowNumber) {
+            session->insertTablet(tablet, true);
+            tablet.reset();
+        }
     }
-    if (tablet.rowSize == tablet.maxRowNumber) {
-      session->insertTablet(tablet, true);
-      tablet.reset();
-    }
-  }
 
-  if (tablet.rowSize != 0) {
-    session->insertTablet(tablet);
-    tablet.reset();
-  }
+    if (tablet.rowSize != 0) {
+        session->insertTablet(tablet);
+        tablet.reset();
+    }
 }
 
 void insertTablets() {
-  pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
-  pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
-  pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
-  vector<pair<string, TSDataType::TSDataType>> schemas;
-  schemas.push_back(pairA);
-  schemas.push_back(pairB);
-  schemas.push_back(pairC);
-
-  Tablet tablet1("root.sg1.d1", schemas, 100);
-  Tablet tablet2("root.sg1.d2", schemas, 100);
-  Tablet tablet3("root.sg1.d3", schemas, 100);
-
-  map<string, Tablet*> tabletMap;
-  tabletMap["root.sg1.d1"] = &tablet1;
-  tabletMap["root.sg1.d2"] = &tablet2;
-  tabletMap["root.sg1.d3"] = &tablet3;
-
-  for (int64_t time = 0; time < 100; time++) {
-    int row1 = tablet1.rowSize++;
-    int row2 = tablet2.rowSize++;
-    int row3 = tablet3.rowSize++;
-    tablet1.timestamps[row1] = time;
-    tablet2.timestamps[row2] = time;
-    tablet3.timestamps[row3] = time;
-
-    for (int i = 0; i < 3; i++) {
-      tablet1.values[i][row1] = to_string(i);
-      tablet2.values[i][row1] = to_string(i);
-      tablet3.values[i][row1] = to_string(i);
+    pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
+    pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
+    pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
+    vector<pair<string, TSDataType::TSDataType>> schemas;
+    schemas.push_back(pairA);
+    schemas.push_back(pairB);
+    schemas.push_back(pairC);
+
+    Tablet tablet1("root.sg1.d1", schemas, 100);
+    Tablet tablet2("root.sg1.d2", schemas, 100);
+    Tablet tablet3("root.sg1.d3", schemas, 100);
+
+    map<string, Tablet*> tabletMap;
+    tabletMap["root.sg1.d1"] = &tablet1;
+    tabletMap["root.sg1.d2"] = &tablet2;
+    tabletMap["root.sg1.d3"] = &tablet3;
+
+    for (int64_t time = 0; time < 100; time++) {
+        int row1 = tablet1.rowSize++;
+        int row2 = tablet2.rowSize++;
+        int row3 = tablet3.rowSize++;
+        tablet1.timestamps[row1] = time;
+        tablet2.timestamps[row2] = time;
+        tablet3.timestamps[row3] = time;
+
+        for (int i = 0; i < 3; i++) {
+            tablet1.values[i][row1] = to_string(i);
+            tablet2.values[i][row1] = to_string(i);
+            tablet3.values[i][row1] = to_string(i);
+        }
+        if (tablet1.rowSize == tablet1.maxRowNumber) {
+            session->insertTablets(tabletMap, true);
+
+            tablet1.reset();
+            tablet2.reset();
+            tablet3.reset();
+        }
     }
-    if (tablet1.rowSize == tablet1.maxRowNumber) {
-      session->insertTablets(tabletMap, true);
 
-      tablet1.reset();
-      tablet2.reset();
-      tablet3.reset();
+    if (tablet1.rowSize != 0) {
+        session->insertTablets(tabletMap, true);
+        tablet1.reset();
+        tablet2.reset();
+        tablet3.reset();
     }
-  }
-
-  if (tablet1.rowSize != 0) {
-    session->insertTablets(tabletMap, true);
-    tablet1.reset();
-    tablet2.reset();
-    tablet3.reset();
-  }
 }
 
 void insertRecords() {
-  string deviceId = "root.sg1.d1";
-  vector<string> measurements;
-  measurements.push_back("s1");
-  measurements.push_back("s2");
-  measurements.push_back("s3");
-
-  vector<string> deviceIds;
-  vector<vector<string>> measurementsList;
-  vector<vector<string>> valuesList;
-  vector<int64_t> timestamps;
-  vector<string>* values;
-
-  for (int64_t time = 0; time < 500; time++) {
-      values = new vector<string>();
-      values->push_back("1");
-      values->push_back("2");
-      values->push_back("3");
-
-      deviceIds.push_back(deviceId);
-      measurementsList.push_back(measurements);
-      valuesList.push_back(*values);
-      timestamps.push_back(time);
-      if (time != 0 && time % 100 == 0) {
-        session->insertRecords(deviceIds, timestamps, measurementsList, 
valuesList);
-        deviceIds.clear();
-        measurementsList.clear();
-        valuesList.clear();
-        timestamps.clear();
-      }
+    string deviceId = "root.sg1.d1";
+    vector<string> measurements;
+    measurements.push_back("s1");
+    measurements.push_back("s2");
+    measurements.push_back("s3");
+
+    vector<string> deviceIds;
+    vector<vector<string>> measurementsList;
+    vector<vector<string>> valuesList;
+    vector<int64_t> timestamps;
+    vector<string>* values;
+
+    for (int64_t time = 0; time < 500; time++) {
+        values = new vector<string>();
+        values->push_back("1");
+        values->push_back("2");
+        values->push_back("3");
+
+        deviceIds.push_back(deviceId);
+        measurementsList.push_back(measurements);
+        valuesList.push_back(*values);
+        timestamps.push_back(time);
+        if (time != 0 && time % 100 == 0) {
+            session->insertRecords(deviceIds, timestamps, measurementsList, 
valuesList);
+            deviceIds.clear();
+            measurementsList.clear();
+            valuesList.clear();
+            timestamps.clear();
+        }
     }
 
     session->insertRecords(deviceIds, timestamps, measurementsList, 
valuesList);
 }
 
 void nonQuery() {
-  session->executeNonQueryStatement("insert into root.sg1.d1(timestamp,s1) 
values(200, 1);");
+    session->executeNonQueryStatement("insert into root.sg1.d1(timestamp,s1) 
values(200, 1);");
 }
 
 void query() {
-  SessionDataSet* dataSet;
-  dataSet = session->executeQueryStatement("select * from root.sg1.d1");
-  cout << "timestamp" << "  ";
-  for (string name : dataSet->getColumnNames()) {
-    cout << name << "  ";
-  }
-  cout << endl;
-  dataSet->setBatchSize(1024);
-  while (dataSet->hasNext())
-  {
-    cout << dataSet->next()->toString();
-  }
-  
-  dataSet->closeOperationHandle();
+    unique_ptr<SessionDataSet> dataSet = 
session->executeQueryStatement("select * from root.sg1.d1");
+    cout << "timestamp" << "  ";
+    for (string name : dataSet->getColumnNames()) {
+      cout << name << "  ";
+    }
+    cout << endl;
+    dataSet->setBatchSize(1024);
+    while (dataSet->hasNext())
+    {
+      cout << dataSet->next()->toString();
+    }
+
+    dataSet->closeOperationHandle();
 }
 
 void deleteData() {
-  string path = "root.sg1.d1.s1";
-  int64_t deleteTime = 99;
-  session->deleteData(path, deleteTime);
+    string path = "root.sg1.d1.s1";
+    int64_t deleteTime = 99;
+    session->deleteData(path, deleteTime);
 }
 
 void deleteTimeseries() {
@@ -256,7 +255,7 @@ void deleteTimeseries() {
 }
 
 void queryLast() {
-    SessionDataSet *dataSet = session->executeQueryStatement("select last 
s1,s2,s3 from root.sg1.d1");
+    unique_ptr<SessionDataSet> dataSet = 
session->executeQueryStatement("select last s1,s2,s3 from root.sg1.d1");
     for (string name: dataSet->getColumnNames()) {
         cout << name << "  ";
     }

Reply via email to