AWS SDK for C++  1.7.233
AWS SDK for C++
AWSString.h
Go to the documentation of this file.
1 /*
2  * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  * http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 #pragma once
17 
18 #include <aws/core/Core_EXPORTS.h>
19 
21 
22 #include <functional>
23 #include <string>
24 
25 namespace Aws
26 {
27 
28 #if defined(_GLIBCXX_FULLY_DYNAMIC_STRING) && _GLIBCXX_FULLY_DYNAMIC_STRING == 0 && defined(__ANDROID__)
29 
30 /*
31 using std::string with shared libraries is broken on android when using gnustl
32 due to the platform-level decision to set _GLIBCXX_FULLY_DYNAMIC_STRING to 0
33 
34 The problem:
35 
36 (1) _GLIBCXX_FULLY_DYNAMIC_STRING is set to 0 in Android's c++config.h for gnustl
37 (2) The optimization that this enables is completely broken if using shared libraries and there is no way to opt out of using it.
38  An optimization that uses a comparison to a static memory address is death for shared libraries.
39 
40 Supposing you have a shared library B that depends on another shared library A. There are a variety of inocuous scenarios where you end up crashing
41 in the std::basic_string destructor because it's attempting to free a static memory address (&std::string::_Rep_Base::_S_empty_rep_storage -- you'll need to temporarily
42 flip the struct to "public:" in order to take this address from your code).
43 If you take the address of this location, you will get two
44 different answers depending on whether you query it in library A or library B (oddly enough, if you look the symbol itself up, it only shows up as public weak in
45 libgnustl_shared.so). When the string destructor is run from the context of library B, the _Rep::_M_dispose function will end up attempting to free
46 an address that is static memory (from library A).
47 
48 
49 Lessons (with the empty string optimization forced on you):
50  (1) You can't move std::strings across shared libraries (as a part of another class, Outcome in our case)
51  (2) If you default initialize a std::string member variable, you can't have a mismatched constructor/destructor pair such that one is in a cpp file and the other
52  is missing/implicit or defined in the header file
53 
54 Solutions:
55 
56 Use libc++ rather than gnustl
57 
58 For those who must use gnustl, we have provided a working solution by cobbling together a set of hacks:
59 
60 We prevent the empty string optimization from ever being run on our strings by:
61  (1) Make Aws::Allocator always fail equality checks with itself; this check is part of the empty string optimization in several std::basic_string constructors
62  (2) All other cases are prevented by turning Aws::String into a subclass whose default constructor and move operations go to baseclass versions which will not
63  perform the empty string optimization
64 
65 Those changes prevent crashes, but lead to very poor performance when using a string stream; every character added will result in multiple copies of the entire
66 string (ie, quadratic).
67 
68 To fix the performance problems, we have put together a set of replacement classes, SimpleStreamBuf and SimpleStringStream, that
69 replace std::stringstream and std::stringbuf in SDK code. These replacements use raw buffers rather than strings in order to
70 avoid the performance issues.
71 
72 This solution is only enabled if using gnustl on Android. In all other situations, normal STL types are used.
73 */
74 
75 using AndroidBasicString = std::basic_string< char, std::char_traits< char >, Aws::Allocator< char > >;
76 
77 class String : public AndroidBasicString
78 {
79  public:
80  using Base = AndroidBasicString;
81 
82  String() : Base("") {} // allocator comparison failure will cause empty string optimisation to be skipped
83  String(const String& rhs ) : Base(rhs) {}
84  String(String&& rhs) : Base(rhs) {} // DO NOT CALL std::move, let this go to the const ref constructor
85  String(const AndroidBasicString& rhs) : Base(rhs) {}
86  String(AndroidBasicString&& rhs) : Base(rhs) {} // DO NOT CALL std::move, let this go to the const ref constructor
87  String(const char* str) : Base(str) {}
88  String(const char* str_begin, const char* str_end) : Base(str_begin, str_end) {}
89  String(const AndroidBasicString& str, size_type pos, size_type count) : Base(str, pos, count) {}
90  String(const String& str, size_type pos, size_type count) : Base(str, pos, count) {}
91  String(const char* str, size_type count) : Base(str, count) {}
92  String(size_type count, char c) : Base(count, c) {}
93  String(std::initializer_list<char> __l) : Base(__l) {}
94 
95  template<class _InputIterator>
96  String(_InputIterator __beg, _InputIterator __end) : Base(__beg, __end) {}
97 
98  String& operator=(const String& rhs) { Base::operator=(rhs); return *this; }
99  String& operator=(String&& rhs) { Base::operator=(rhs); return *this; } // might be ok to use std::move (base class uses swap) but let's be safe
100  String& operator=(const AndroidBasicString& rhs) { Base::operator=(rhs); return *this; }
101  String& operator=(AndroidBasicString&& rhs) { Base::operator=(rhs); return *this; } // might be ok to use std::move (base class uses swap) but let's be safe
102  String& operator=(const char* str) { Base::operator=(str); return *this; }
103 };
104 
105 #else
106 
107 using String = std::basic_string< char, std::char_traits< char >, Aws::Allocator< char > >;
108 
109 #ifdef _WIN32
110 using WString = std::basic_string< wchar_t, std::char_traits< wchar_t >, Aws::Allocator< wchar_t > >;
111 #endif
112 
113 #endif // __ANDROID
114 
115 } // namespace Aws
116 
117 
118 
std::allocator< T > Allocator
Definition: AWSAllocator.h:94
int count
Definition: cJSON.h:215
std::basic_string< char, std::char_traits< char >, Aws::Allocator< char > > String
Definition: AWSString.h:107