2015-09-23 2 views
-1

Я использую Rapidjson и заметил, что когда я включаю оптимизацию в g ++ (-O1/-O2/-O3), я получаю ошибку сегментации. Я думаю, что я отследил его до функции GenericValue & AddMember() в пределах quickjson.Ошибка Rapidjson seg с оптимизацией g ++

GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { 
    RAPIDJSON_ASSERT(IsObject()); 
    RAPIDJSON_ASSERT(name.IsString()); 

    Object& o = data_.o; 
    if (o.size >= o.capacity) { 
     if (o.capacity == 0) { 
      o.capacity = kDefaultObjectCapacity; 
      o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))); 
     } 
     else { 
      SizeType oldCapacity = o.capacity; 
      o.capacity += (oldCapacity + 1)/2; // grow by factor 1.5 
      o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member))); 
     } 
    } 
    o.members[o.size].name.RawAssign(name); 
    o.members[o.size].value.RawAssign(value); 
    o.size++; 
    return *this; 
} 

При отладке, можно видеть, что kDefaultObjectCapacity (оптимизируется выход (это статический Const SizeType kDefaultObjectCapacity = 16)

Поэтому линия "o.capacity = kDefaultObjectCapacity;" не выполняется и таНос является mallocing 0 байт, а затем пытается бросить его.

Почему это статическая Const удаляется?

Я попытался сделать объект & о как летучий и статическом, neithe r работал. Любые идеи?

Благодаря Will

EDIT: я не могу легко запускать тесты, как это на встроенной платформе, rapidjson построена с использованием Buildroot в данный момент. Я попробовал модульные тесты, но не мог заставить их идти по цели.

Я могу взглянуть на предоставление сборки, но это часть большого приложения, поэтому может быть трудно найти правильный бит.

Для информации, это метод, который вызывает код rapidjson и это, где проблема, кажется:

int16_t FrontEndJSONHandlers::get_run_cfg_packer(JSONEngine& json_engine, char *message, int32_t *length) 
{ 
Document doc; 

// Need to pack an empty request to get the data 
doc.SetObject(); 
doc.AddMember(JSONRPC_MEMBER, JSONRPC_VERSION, doc.GetAllocator()); 
doc.AddMember(METHOD_MEMBER, JSON_RPC_METH_GET_RUN_CFG, doc.GetAllocator()); 
doc.AddMember(ID_MEMBER, json_engine.GetNextMessageID(), doc.GetAllocator()); 

// Format the message 
json_engine.FormatMessageAndRegisterResponseHandler(&doc, &message, &length, get_run_cfg_handler); 

return 0; 
} 

Если я документ документ статичен, он не сегмы вины - не уверен в том, это лучший способ обойти это?

+0

Можете ли вы показать нам сгенерированную сборку, как с оптимизацией, так и без нее? (См. Https://stackoverflow.com/questions/137038/how-do-you-get-assembler-output-from-c-c-source-in-gcc) – robert

+0

Выполняют ли модульные тесты в пакете fastjson? Возможно, приложение имеет поврежденную память. –

ответ

1

Ваш код выглядит довольно плохо, и поэтому я подозреваю, что вы также не понимаете, что видите в отладчике. Попробуйте фиксируя ошибки первых, перед тем беспокоясь о том, что оптимизатор может делать:

Оказывается, что часть вашего намерения для o.capacity, чтобы в конечном итоге > (или, может быть, вы хотели >=) o.size

Но вы рассмотрели случай o.size > kDefaultObjectCapacity, когда o.proacity начинается с нуля? Более серьезно, ваш комментарий об увеличении в 1,5 раза неверен для кода, который уменьшает емкость. Вы, вероятно, предназначен oldCapacity*3/2

if (o.size >= o.capacity) { 
    if (o.capacity == 0) { 
     o.capacity = kDefaultObjectCapacity; 
     o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))); 
    } 
    else { 
     SizeType oldCapacity = o.capacity; 
     o.capacity += (oldCapacity + 1)/2; // grow by factor 1.5 
     o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member))); 
    } 
} 

Edit: я ошибся в значительной части выше. Но я все же думаю, что неправильное понимание того, что было замечено в отладчике, является более вероятным объяснением того, что оптимизатор нарушает этот код.

Был ли упомянутый десятичный знак «90», или он мог быть шестнадцатеричным? Оптимизатор, конечно же, мог пропустить умножение на sizeof(Member) и перейти непосредственно к результату этого умножения.

+0

'> =' правильно. Когда 'size == capacity' означает, что хранилище просто заполнено и ему необходимо увеличить емкость хранилища. А также обратите внимание, что строка 'o.capacity + = (oldCapacity + 1)/2', которая добавляет' ceil (oldCapacity * 0.5) ', чтобы сделать коэффициент увеличения 1.5. –

+0

Извините, только что отредактированный пост, я сделал опечатку. o.capacity изначально 0 байтов, поэтому он переходит в «if (o.capacity == 0) {». Затем он пропускает строку, чтобы установить o.capacity в kDefaultObjectCapacity, а o.proacity все равно 0, когда вызывается Malloc. –

+0

Теперь, когда вы удалили «90», которые я так много читал, в моем ответе не останется никакой ценности. Мой альтернативный ответ: я все равно не верю, что оптимизатор пошел так плохо. Поэтому нам нужно увидеть достаточно большой фрагмент, желательно целый модуль, который можно скомпилировать, но, по крайней мере, достаточно, чтобы включить определение указанной вами константы, а также объявление членов данных «Object». Если это все в загруженном вами коде, ссылка будет приятной, так как я не знаю, как ее искать. – JSF

0

У меня возникла аналогичная проблема, с компиляцией с GCC 4.9: У меня возникает ошибка сегментации, когда указан флаг оптимизации (-On).Это очень легко дублировать, вот код:

//... 
#include "extern/rapidjson/document.h" 
//... 
void* MyThread(void*) 
{ 
    std::cout << "Start of MyThread" << std::endl; 

    rapidjson::Document doc; 
    doc.Parse("{ \"NAME\": \"Peter\", \"AGE\": 38, \"Male\": true}"); 

    std::cout << "End!"; 

    return NULL; 
} 

int main(int argc, char** argv) 
{ 
    pthread_t thread; 

    pthread_create(&thread, NULL, &MyThread, NULL); 

    std::string str; 
    std::cout << "Press <Return>" << std::endl; 
    std::getline(std::cin, str); 

    return 0; 
} 

Ключевым моментом здесь является документ создается и анализируется в отдельном потоке. Если мы назовем «MyThread (NULL)» непосредственно в main(), мы не получим никакой ошибки.

Аналогичный код с Visual Studio 2012, оптимизированный, отлично работает. Я провел анализ кода VS и ошибок не обнаружено. Единственным отличием является нарезание резьбы:

std::thread th([] { MyThread(NULL); }); 
th.join(); 

==================================== ===========

Проблема была исправлена ​​после версии 1.0.2. Использование последнего кода отлично работает.

+0

Я предлагаю опубликовать это как новый вопрос («почему сбой версии потока?»). Вы можете поместить комментарий по этому вопросу, ссылаясь на свой новый вопрос, если хотите. Пока нет доказательств того, что это на самом деле ответ на вопрос ОП. –

+0

, хотя я бы предложил вызвать 'pthread_join' до' return 0; 'по крайней мере ... если вы упадете с конца main, тогда он может уничтожить любые статические объекты, которые' quickjson' использовали, а затем ваш поток пытается использовать эти объекты и попадает в неприятности –

+0

Другое дело, что 'cout', возможно, не был потокобезопасным до C++ 11 –

 Смежные вопросы

  • Нет связанных вопросов^_^