首页 > 解决方案 > C++ Builder 10.2 Tokyo > JSON > 用 JsonValue->Free() 替换 JSONvalue 导致“访问冲突”

问题描述

我的环境:

我正在寻找替换 JSON 值的方法。然后,我遇到了以下问答。

在德尔福:

JoPair.JsonValue.Free;
JoPair.JsonValue := TJSONNumber.Create(123);

在此之后,我想,它将在 C++ Builder 中

JoPair->JsonValue->Free();
JoPair->JsonValue = new TJSONNumber(123);

但是,它在 ToString() 中导致了“访问冲突”错误;

相反,我注释掉了JoPair->JsonValue->Free();,然后没问题。

问题:

在 C++ Buidler 中,我是否需要 Free JoPair->JsonValue?

但是如果不释放 JsonValue,可能会导致内存泄漏。

源代码

以下是我检查的实际代码

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <DBXJSON.hpp> // for JSON
#include <memory> // for unique_ptr
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    String srcFileName = L"test.json";  // source
    String dstFileName = L"out.json";  // destination
    String targetKeySubString = L"hogehoge";  //
    String targetValue = "9";

    // 1. read JSON strings
    std::unique_ptr<TStringList> slread(new TStringList);
    slread->LoadFromFile(srcFileName);

    // 2. replace values for the key (target is checked by substring)
    TJSONObject *jsonObj;
    String jsonKey, jsonValue;
    TJSONPair *pairObj;

    std::unique_ptr<TStringList> slwrite(new TStringList);

    for(int li=0; li < slread->Count; li++) { // file line index
        String jsonText = slread->Strings[li];
        // this is needed for avoiding error caused by the file path treating backslash
        jsonText = StringReplace(jsonText, L"\\", L"\\\\", TReplaceFlags()<<rfReplaceAll);
        //
        jsonObj = dynamic_cast<TJSONObject*>(TJSONObject::ParseJSONValue(jsonText));

        for(int pi=0; pi < jsonObj->Size(); pi++) { // pair index
            pairObj = jsonObj->Get(pi);
            jsonKey = pairObj->JsonString->Value();
            jsonValue = pairObj->JsonValue->Value();

            if (jsonKey.Pos(targetKeySubString) == 0) {
                continue;
            }

            // replace value
            // (ref: https://stackoverflow.com/questions/33426576/delphi-xe7-how-to-change-a-json-value-using-system-json-versus-superobject)
            //
            //pairObj->JsonValue->Free();  // commented out because this causes "access violation" in ToString()
            pairObj->JsonValue = new TJSONString(targetValue);

            // debug
            //ShowMessage(jsonKey + ":" + jsonValue);
        }

        slwrite->Add(jsonObj->ToString());
    }
    jsonObj->Free();

    // 3. output 
    slwrite->SaveToFile(dstFileName);

    ShowMessage(L"Done");

}
//---------------------------------------------------------------------------

例子

{"1_hogehoge":"3", "2_fugafuga":"1","3_hogehoge":"4", "4_fugafuga":"1", "5_hogehoge":"5", "6_fugafuga":"9"}
{"1_hogehoge":"9","2_fugafuga":"1","3_hogehoge":"9","4_fugafuga":"1","5_hogehoge":"9","6_fugafuga":"9"}

源代码(10.2 东京)

我已经更新了源代码。还是一样的问题。

我也使用ToJSON()而不是ToString()相同的错误(访问冲突)`。

我也尝试过使用std::unique_ptr,这导致了另一个错误。所以我现在放弃了std::unique_ptr这个话题(最好单独研究)。

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <System.JSON.hpp>
#include <memory> // for unique_ptr
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    String srcFileName = L"test.json";  // source
    String dstFileName = L"out.json";  // destination
    String targetKeySubString = L"hogehoge";  //
    String targetValue = "9";

    // 1. read JSON strings
    std::unique_ptr<TStringList> slread(new TStringList);
    slread->LoadFromFile(srcFileName);

    // 2. replace values for the key (target is checked by substring)
    TJSONObject *jsonObj;
    //std::unique_ptr<TJSONObject> jsonObj(new TJSONObject);
    String jsonKey, jsonValue;
    TJSONPair *pairObj;

    std::unique_ptr<TStringList> slwrite(new TStringList);

    for(int li=0; li < slread->Count; li++) { // file line index
        String jsonText = slread->Strings[li];
        // this is needed for avoiding error caused by the file path treating backslash
        jsonText = StringReplace(jsonText, L"\\", L"\\\\", TReplaceFlags()<<rfReplaceAll);
        //
        jsonObj = dynamic_cast<TJSONObject*>(TJSONObject::ParseJSONValue(jsonText));

        if (jsonObj == NULL) {
            continue;
        }

        for(int pi=0; pi < jsonObj->Count; pi++) { // pair index
            pairObj = jsonObj->Pairs[pi];
            jsonKey = pairObj->JsonString->Value();
            jsonValue = pairObj->JsonValue->Value();

            if (jsonKey.Pos(targetKeySubString) == 0) {
                continue;
            }

            // replace value
            // (ref: https://stackoverflow.com/questions/33426576/delphi-xe7-how-to-change-a-json-value-using-system-json-versus-superobject)
            //
            //pairObj->JsonValue->Free();  // commented out because this causes "access violation" in ToString()

            delete pairObj->JsonValue;

            pairObj->JsonValue = new TJSONString(targetValue);

            // debug
            //ShowMessage(jsonKey + ":" + jsonValue);
        }
        //String res = jsonObj->ToJSON();   // *** access violation ***
        String res = jsonObj->ToString();  // *** access violation ***
        slwrite->Add(res);
        jsonObj->Free();
    }

    // 3. output
    slwrite->SaveToFile(dstFileName);

    ShowMessage(L"Done");

}
//---------------------------------------------------------------------------

标签: jsonc++builder

解决方案


推荐阅读