json - C++ Builder 10.2 Tokyo > JSON > 用 JsonValue->Free() 替换 JSONvalue 导致“访问冲突”
问题描述
我的环境:
- RadStudio 10.2 东京
- 在 Windows 10(64 位)v1809 上工作
我正在寻找替换 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");
}
//---------------------------------------------------------------------------
解决方案
推荐阅读
- react-native - Cannot Reload React Native App on Mobile Using Expo
- sql - SQL - 非常慢的记录检索
- delegates - 何时为代表使用 UFUNCTION
- php - PHP BBCODE 解析器 XSS
- java - 如何将对象存储在 ArrayList 中并打印出来?
- kotlin - 迁移到非实验性协程
- apache - 如何使用单个 RewriteRule 通过 .htaccess 将所有内容重定向到 https 和非 www?
- unity3d - 使用 Camera.main.ScreenToWorldPoint 时出现对象引用错误
- javascript - 将最大高度设置为已经响应的 D3 圆环图
- ruby-on-rails - 如何访问 Rails API 中的请求标头?