New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question about the correct usage of AddMember and Value #412
Comments
Small update, I tested small code on iOS, Android and Kindle Fire HDX with this result.
On iOS iPhone or iPad, Android no problem. On Kindle crash every time in addMember function. B)
On iOS iPhone or iPad, no problem. On Android I have random crash. On Kindle crash every time. C)
After reading all rapidjson issues I found (C) code. And works on all tested platforms. Thx |
Thank you for your report. I think the use of StringRef is correct is your code. The problem seems related to memory allocation in some platforms. There has been some similar reports in the past but no diagnosis can be found. Using Since you found that in some cases it always crash, that may be a very good opportunity to dig out the cause exactly. I hope you may help diagnoses how it is crashed. It may be related to address alignment or similar issues. I hope we can work together to resolve this. |
Hi here is the test for different memory align no change for now, still crash on Kindle. I tried current master branch and 1.0.2 from cocos2d-x. For both rapidjson version I have same result. Here are dumps with master branch: Maybe this will help. I saw that someone report similar issue on arm only in release mode.
There is no crash. Crash occurs only with these flags.
Used in test: mac OS X 10.10.5, ndk toolchain: 4.9, android target 22, min sdk 19. |
The dump shows that Since it only happens in release mode, it may be hard to gdb or something. Please try printing the intermediate variables (via some kind of In class void* Malloc(size_t size) {
printf("Malloc(%zu)\n", size); fflush(stdout);
if (!size)
return NULL;
size = RAPIDJSON_ALIGN(size);
printf("aligned size = %zu\n", size); fflush(stdout);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
chunkHead_->size += size;
printf("buffer = %p", buffer); fflush(stdout);
return buffer;
}
// ...
void AddChunk(size_t capacity) {
printf("AddChunk(%zu)\n", capacity); fflush(stdout);
if (!baseAllocator_) {
printf("Going to new BaseAllocator()"); fflush(stdout);
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
printf("ownBaseAllocator = %p\n", ownBaseAllocator); fflush(stdout);
}
size_t s = RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity;
printf("s = %zu\n", s); fflush(stdout);
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(s));
printf("chunk = %p", chunk); fflush(stdout);
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
chunkHead_ = chunk;
} Thank you. |
Hi, I replace your log with LOGD. In the dump all is ok until this code is accesed. App crash when chunkHead_ is accessed for some reason. Im unable to log something about chunkHead_ like if (chunkHead_ == 0 or !=0) always crash. But as you can see other work with rapidjson before with malloc or add chunk works fine.
Here is the dump. I tried to duplicate code like this, and after that crash is very random.
When there is no crash code continue with this log (09-04 10:22:34.222). To be sure I clean function to have only rj code, function is called every 5 sec from timer.
Another test, MainDialog::checkTask is called after 20sec. Time to process all network task before fce is called. |
From
I suspect that
may relate to reading at the null pointer. You may check (this == 0) at the beginning of the functions. I think Hum. Then the root of problem should be at the constructor of |
You are right, is null. That the reason why always crash when I acces chunkHead_. Let me know what we need to debug in document.h
|
The explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
}
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
} I am quite sure that the However, it seems quite strange whatever these happens... |
Perhaps on some mobile platforms
|
@mloskot exceptions are disabled and crash happen only in release mode not in debug. When excp enabled in release mode there are no debug information due release mode. Only what we get from backtrace. @miloyip I loged both allocators and defautl ctor is called, but after that, allocator Malloc this == 0 is true, is it possible?
Some log before crash works fine.
Very strange is when I add two LOGD functions all works, without them code always crash.
Here is the log with two LOGD functions.
Commented LOGD for allocator_ in both constructors, still works. Also when commented second and uncommented first LOGD still works.
Both commented added another LOGD before call new, and again Malloc this == 0 is true for allocator after ctor was called. Any tip why allocator is null after his ctor is called?
|
I get something more from ndk-stack -sym .... about crash
We already know that...
This is new...
|
try to use it in this way: typedef rapidjson::GenericDocument<rapidjson::UTF8<>,rapidjson::CrtAllocator> DocuType;
typedef rapidjson::GenericValue<rapidjson::UTF8<>,rapidjson::CrtAllocator> ElemType;
DocuType doc;
doc.SetArray();
ElemType element(rapidjson::kObjectType);
element.AddMember("Value", ElemType(1234), doc.GetAllocator());
ElemType array(rapidjson::kArrayType);
array.PushBack(element, doc.GetAllocator());
// and so on... |
I can reproduce the problem on Windows 10, Visual Studio 2013 and enabling Application Verifier for my exe file |
@paresy Can you show a minimal reproducible code? |
Unfortunately i was wrong. The Heap Check option was using a lot of memory, which resulted in malloc returning null. So my comment was more related to this (#414) and not a rapidjson bug. Sorry. |
Hi I will test UserBuffer too, mentioned in #414 if my problem will gone. My files are over cca 6k - still small ;) |
@whitegfx did userbuffer solve this for you ? I guess I am facing the same issue (in cocos2d-x) |
Hi @jarsj , no I upgraded to the latest rapidjson and crash is minimal. But there is some news, more users face this problem in different situations (same as me in release mode), take a look into this discussion for the cause and fix/solution. cocos2d/cocos2d-x#16492 |
Thanks @whitegfx. I was able to eventually fix mine by using CrtAllocator. On Sun, Nov 20, 2016 at 11:59 PM, whitegfx notifications@github.com wrote:
Harsh Jain LinkedIn : https://www.linkedin.com/in/jarsj |
I think I am seeing this same issue trying to build rapidjson inside the ardupilot build env for STM32. When I try to call AddMember on a newly created (empty) Object, the object size and capacity are both 0. The code wants to allocate kDefaultObjectCapacity * sizeof(Member) = 16 * 32 = 512 bytes. However, inside CrtAllocator.Malloc() I print the size requested and get 65548 bytes it is trying to malloc. That call to std::malloc(65548) fails and the function returns null. I temporarily hacked the code to request kDefaultObjectCapacity * sizeof(Member) + 2 (so 514 bytes), but inside CrtAllocator.Malloc() it is still reporting that I asked for 65548 bytes (didn't change even though I requested a different value.) I can't figure out why we are calling Malloc(512) and inside CrtAllocator.Malloc() the value is received as 65548. My guess is some sort of confusion/conflict about the size_t datatype? But I can't make the math add up to get from 512 passed to 65548 received? It's almost like there is a memory corruption/overrun bug somewhere and the stack is getting corrupted? The identical code on my linux desktop pc works fine, but I see it also tries to Malloc this same huge nonesense amount of RAM, the main difference is my PC can happily satisfy the request. Anyone have any ideas? |
Ok, following up to my own message, I think I finally figured out the problem on small mcpu's. In allocators.h line #263: static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. This defines how big the actual allocation chunks size is + some additional bytes. My processor can't satisfy a malloc() call for that size buffer. I changed kDefaultChunkCapacity to a far lower value of 1024, and now my code seems to be running ok. I don't know if there's a way to auto set this to a reasonable value with #ifdef magic, or maybe people just have to be warned so they can change to an appropriate value themselves? Hope this helps anyone who's trying to use rapidjson on a small mcpu. Thanks,. |
@clolsonus Thank you! That was exactly my issue, while writing for ESP32. |
Hi to all I have a question regarding the correct usage of AddMember and Value.
I read doc many times, how to create Value and add member with StringRef but still random crashes. (1, 2) they crash, (3,4) I hope that they are ok.
So please correct me if I use the methods in the wrong way. Or link with more examples with different literal and constructs types are welcome.
RAPIDJSON_HAS_STDSTRING is set to default (0).
Error that i get many times but random, differ on used addMember or Value function.
Thank you for your time.
The text was updated successfully, but these errors were encountered: