트러블 슛팅 _ arduinoJson 에러에 대해.

낭만개발자·2020년 12월 29일
0

IOT

목록 보기
2/9
#include <ArduinoJson.h>


      DynamicJsonDocument doc(49152); //12288

      doc["channel"] = 11;
      doc["auth_code"] = "wvgnju";
      JsonArray data = doc.createNestedArray("data");
      
     for(int i=0; i<2048; i++){
          esp_random();
//          strTemp = String(random(0, 1023));
          data.add(random(0, 1023));
        }
          
      serializeJson(doc, value);
      
  Serial.println(value);    
  Serial.println("탄");
  

문제:

간단하게 위의 코드 돌리면 json에 {data : [배열 몇천개]} 이런식으로 나와야 하는데 data:null 로 계속 뜨는것이었다.
(아 물론 JsonArray data가 아니라 doc["data"] 이런식으로 object형식으로 만들었기에 value는 "숫자 숫자 ... "
해서 용량이 더 컸다. )

해결 :

ArduinoJson 홈페이지에서 발견했는데, 메모리 할당을 적게 주면 Null이 나올 수 있단다. 나도 메모리 수치를 좀더 올리면서 테스트 해봤는데 안됬던게 그보다 더 훨씬 올렸어야 하는거임. 내가 데이터가 2048개를 담아야 하는데 실수로 dummy data만들때 for문에 2048번 돌려야 하는데 1024번 돌려서 할당값을 1/2나 적게 착각했던 것이다.
결국 doc()메모리 할당 수치 올림으로써 해결했다

reference : https://arduinojson.org/v6/faq/why-is-the-output-incomplete/

알게된점 :

  1. char[5500] 등등 배열 만들때 조심해야 한다. 아무 생각 없이 배열을 만들었었는데 그게 메모리를 다 잡아 먹는 것이었다. iot쪽 device 다룰때는 앱이나 웹앱과는 달리 메모리 좀더 고려해야 한다.
  1. 약간 귀찮을거 같아 JsonArray안쓰고 걍 Json에 string 값으로 data "val1 val2 val3 ...val2048" 후 받는 쪽에서 Tokenizer로 parsing 하려고 했는데 string 붙이는거랑 array에 담는거랑 용량이 2배 이상 나더라. 무슨 공백 한개씩 있는게 2배 이상이 나지?? 의문은 드는데 확실히 공백 하나하나를 무시 못한다 빅데이터 만질땐. string쓸까 array쓸까 고민하다가 걍 string 써보니까 array를 왜 써야 되는지 알겠더라. 일단 고민을 오래하는것보다 진행해보는게 나을때가 많은 것 같다.

메모리 사용 줄이는 법
1. deserializer 할때..즉 parsing한다면
char[] json ="할당" 은 괜찮은데
const cahr* json 이나 String json = "{.."
아래 자료형은 피하라. read-only라서 copy해야하므로 메모리 더 먹음

  1. heap보다 stack을 써라
    힙에서 할당과 디할당? 은 오버헤드나 fragmentation을 야기한다.
    근데 용량이 많으면 heap 써야함.

3.전역 변수를 피하라
전역 변수는 많은 레벨들에서 나쁘다. 왜냐? 전체 실행 과정에서 계속 살아있으니까!! 다시 말해 항상 RAM을 소비하게 한다.(피곤한 녀석들)

4.String 중복 방지
String클래스는 항상 생성자에 전달 된 문자열의 복사본을 만듭니다.
아래 String s는 생성자임.

String s = "hello" //이러면 한번 복사가 일어난다.
const char* s = "hello" //복사가 아니다. hello 메모리 값을 주는 것이다.

라이브러리에서 메모리 누수 날때

  1. JsonDocument를 전역변수에 선언하지 마라.
    JsonDocument를 재활용 하지 않는다면(=전역 변수 선언 안한다면)
    leak은 일어나지 않는다!
    즉 void loop()안에 나둬라 이말이지.
    2,3도 있는데 loop안에 두면 왠만해선 문제 없을듯.
profile
낭만닥터와 슬의를 보고 저런 개발자가 되어야 겠다고 꿈꿔봅니다.

0개의 댓글