clarify errors

* use macros for logic errors, not input errors
* throw on parsing failure in `operator>>()`, not assert
* throw on malloc, not assert
diff --git a/include/json/assertions.h b/include/json/assertions.h
index d5fd661..07e7f2e 100644
--- a/include/json/assertions.h
+++ b/include/json/assertions.h
@@ -13,6 +13,10 @@
 #include "config.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
 
+/** It should not be possible for a maliciously designed file to
+ *  cause an abort() or seg-fault, so these macros are used only
+ *  for pre-condition violations and internal logic errors.
+ */
 #if JSON_USE_EXCEPTION
 #include <stdexcept>
 #define JSON_ASSERT(condition)                                                 \
@@ -27,7 +31,7 @@
 #define JSON_ASSERT(condition) assert(condition)
 
 // The call to assert() will show the failure message in debug builds. In
-// release bugs we abort, for a core-dump or debugger.
+// release builds we abort, for a core-dump or debugger.
 #define JSON_FAIL_MESSAGE(message)                                             \
   {                                                                            \
     std::ostringstream oss; oss << message;                                    \
diff --git a/include/json/writer.h b/include/json/writer.h
index 2d6dbce..f6fcc9c 100644
--- a/include/json/writer.h
+++ b/include/json/writer.h
@@ -46,7 +46,7 @@
   /** Write Value into document as configured in sub-class.
       Do not take ownership of sout, but maintain a reference during function.
       \pre sout != NULL
-      \return zero on success
+      \return zero on success (For now, we always return zero, so check the stream instead.)
       \throw std::exception possibly, depending on configuration
    */
   virtual int write(Value const& root, std::ostream* sout) = 0;
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index 9ceaf38..32f4d02 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -1994,7 +1994,7 @@
             "Error from reader: %s",
             errs.c_str());
 
-    JSON_FAIL_MESSAGE("reader error");
+    throw std::runtime_error("reader error");
   }
   return sin;
 }
diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
index 46385b9..4e032ce 100644
--- a/src/lib_json/json_value.cpp
+++ b/src/lib_json/json_value.cpp
@@ -87,9 +87,11 @@
     length = Value::maxInt - 1;
 
   char* newString = static_cast<char*>(malloc(length + 1));
-  JSON_ASSERT_MESSAGE(newString != 0,
-                      "in Json::Value::duplicateStringValue(): "
-                      "Failed to allocate string value buffer");
+  if (newString == NULL) {
+    throw std::runtime_error(
+        "in Json::Value::duplicateStringValue(): "
+        "Failed to allocate string value buffer");
+  }
   memcpy(newString, value, length);
   newString[length] = 0;
   return newString;
@@ -108,9 +110,11 @@
                       "length too big for prefixing");
   unsigned actualLength = length + sizeof(unsigned) + 1U;
   char* newString = static_cast<char*>(malloc(actualLength));
-  JSON_ASSERT_MESSAGE(newString != 0,
-                      "in Json::Value::duplicateAndPrefixStringValue(): "
-                      "Failed to allocate string value buffer");
+  if (newString == 0) {
+    throw std::runtime_error(
+        "in Json::Value::duplicateAndPrefixStringValue(): "
+        "Failed to allocate string value buffer");
+  }
   *reinterpret_cast<unsigned*>(newString) = length;
   memcpy(newString + sizeof(unsigned), value, length);
   newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later