2013-08-06 8 views
5

मैं JSON से कुछ पाठ प्राप्त करने के लिए jsmn JSON parser (source code) का उपयोग कर रहा हूं। जेएसएमएन टोकन में डेटा स्टोर करता है, लेकिन टोकन कोई डेटा नहीं रखता है, तो वे इसके बजाय JSON स्ट्रिंग में टोकन सीमाओं को इंगित करते हैं।यह विधि सेगमेंटेशन गलती क्यों फेंकती है?

  • वस्तु [0..31]
  • स्ट्रिंग [3..7], स्ट्रिंग [12..16], स्ट्रिंग [20..23]
  • : उदाहरण के लिए, jsmn तरह टोकन पैदा करेगा
  • संख्या [27..29]

इस विधि (स्ट्रिंग वस्तुओं के लिए) उन मूल्यों के बीच वास्तविक पात्रों को पुनः प्राप्त करने के लिए इस्तेमाल किया जाता है:

char* getTextFromJSON(const char *json) 
{ 
    if (!json) return NULL; 

    json_parser p; 
    #define N_TOKENS 15 // this normally would be at the start of the file 
    jsontok_t tokens[N_TOKENS]; 

    initJsonParser(&p); 
    int err parseJson(&p, json, tokens, N_TOKENS); 
    if (err) { 
    fprintf(stdout, "Error parsing JSON: %d\n", err); 
    return NULL; 
    } 
    for (int i = 0; i < N_TOKENS; ++i) { 
     jsontok_t *key = &tokens[i]; 
     if (!memcmp("utterance", &json[key->start], (size_t) (key->end - key->start))) { 
      ++key; 
      return strndup(&json[key->start], (size_t)(key->end - key->start)); 
     } 
    } 
    return NULL; 
} 

यहाँ कुछ JSON उदाहरण हैं कि wo पार्सर में डाल दिया uld:

  • {"status":0,"id":"432eac38858968c108899cc6c3a4bade-1","hypotheses":[{"utterance":"test","confidence":0.84134156}]}
  • {"status":5,"id":"695118aaa3d01dc2ac4aa8054d1e5bb0-1","hypotheses":[]}

विधि करने के लिए पहले उदाहरण JSON गुजर पर, मैंने "परीक्षण" की उम्मीद मूल्य प्राप्त विधि से लौट आए। हालांकि, विधि में खाली JSON को पारित करने पर, मुझे सशर्त if कथन पर for लूप के 8 वें पुनरावृत्ति पर सेगमेंटेशन गलती मिलती है।

कोई सुझाव? -> and-> अंत शुरू

key->start: 0x00000000 
key->end - key->start: 0x00000046 
key->start: 0x00000002 
key->end - key->start: 0x00000006 
key->start: 0x0000000A 
key->end - key->start: 0x00000001 
key->start: 0x0000000D 
key->end - key->start: 0x00000002 
key->start: 0x00000012 
key->end - key->start: 0x00000022 
key->start: 0x00000037 
key->end - key->start: 0x0000000A 
key->start: 0x00000043 
key->end - key->start: 0x00000002 
key->start: 0x3A7B3188 
key->end - key->start: 0x7A0F0766 
+0

तुम सच में पारित करने के लिए करना चाहते हैं 'और जेसन' memcpy' करने के लिए [..] '? –

+0

@UchiaItachi उस विधि में कोई 'memcpy' नहीं है ... – syb0rg

+1

'(key-> start)' के मानों को मुद्रित करने के लिए अपने लूप में 'printf()' कथन दें, और '(key-> end - key -> शुरू करें) 'हेक्स में (यानी:' printf ("0x% 08X", वैल) '। मैं आपकी इनपुट स्ट्रिंग,' जेसन' की ओर झुका रहा हूं, उम्मीद से कम है, और आप एक अवैध सूचक पास कर रहे हैं। – DevNull

उत्तर

1

आपका tokens[] सरणी अप्रारंभीकृत है। इससे आपकी सीजी गलती हो रही है। tokens[] को कुछ करने के लिए प्रारंभ करें और फिर अपने for() लूप के दौरान प्रारंभ/समाप्ति फ़ील्ड में उस प्रारंभिक मान की जांच करें।

उदाहरण के लिए, मैं शायद tokens[] (memset(&tokens, 0, sizeof(tokens)); माध्यम से) और लंबाई शून्य (key->end - key->start) के लिए पाश की जांच से प्रत्येक यात्रा के दौरान शून्य करने के लिए प्रारंभ करता है, तो टोकन वास्तव में यह memcmp() को पार करने से पहले मान्य है देखने के लिए चाहते हैं। यदि टोकन की लंबाई शून्य है तो break; के साथ लूप से बाहर निकलें।

(या, एक टोकन एक वैध शून्य लंबाई हो सकता है, कुछ अन्य मूल्य का उपयोग करें।)

+2

मैं इस जवाब को स्वीकार करने जा रहा हूं क्योंकि यह मुझे समाधान के सबसे नज़दीक मिला है। मैंने सुझाव दिया जैसा मैंने सुझाव दिया था, लेकिन मैंने रिक्त टोकन के लिए एक टेस्ट केस भी जोड़ा ('if (! Memcmp (" ", और json [key-> start], (size_t) (key-> end - key-> प्रारंभ करें)) वापस लौटें; ')। अब कोड सेगमेंटेशन गलती नहीं देता है। – syb0rg

4

संपादित स्रोत कोड को देखने के बाद ...

for (i = parser->toknext; i < num_tokens; i++) { 
    jsmn_fill_token(&tokens[i], JSMN_PRIMITIVE, -1, -1); 
} 

यह संरचनाओं के सभी initializes लेकिन:

यहाँ हेक्स मान रहे हैं -1 बराबर होगा, यही कारण है कि memcmp विफल रहा है।

for (int i = 0; i < N_TOKENS; ++i) { 
    jsontok_t *key = &tokens[i]; 
    if (key->start == -1) return NULL; 
    if (!memcmp("utterance", &json[key->start], (size_t) (key->end - key->start))) { 
     ++key; 
     return strndup(&json[key->start], (size_t)(key->end - key->start)); 
    } 
} 

-1 -1 मूल्य के लिए जांच -> प्रारंभ या -> अंत पर्याप्त होना चाहिए। इससे पहले कि आप, parseJson() को इसे पारित तो एक बार आप (अपने दूसरे उदाहरण में सातवें एक) पिछले टोकन परे पुनरावृति आप अप्रारंभीकृत बकवास पते के मूल्यों पर memcmp() को चलाने के लिए कोशिश कर रहे हैं

+0

अभी भी सेगमेंटेशन गलती हो रही है:/ – syb0rg

+0

@ syb0rg - आप कभी भी पार्सजन (...) के नतीजे की जांच नहीं करते हैं, आपको केवल तब ही आगे बढ़ना चाहिए जब वह फ़ंक्शन JSMN_SUCCESS लौटाता है। –

+0

मैंने अपडेट किया है विधि जो परीक्षण की स्थिति पेश करती है। यह अभी भी एक सेगमेंटेशन गलती देता है। आपके द्वारा दी गई सहायता के लिए – syb0rg

संबंधित मुद्दे