Skip to content
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

C4996 error and warning with Visual Studio #463

Closed
prsyahmi opened this issue Feb 19, 2017 · 8 comments
Closed

C4996 error and warning with Visual Studio #463

prsyahmi opened this issue Feb 19, 2017 · 8 comments
Assignees
Milestone

Comments

@prsyahmi
Copy link

Using latest commit, C4996 errors and warnings spew on every string manipulation function calls:

  • std::strcpy (Warning)
  • std::strcat (Warning)
  • std::copy (Error - compile fail) on non-iterator/pointer destination

Error C4996 'std::copy::_Unchecked_iterators::_Deprecate': Call to 'std::copy' with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'

changing std::copy(m_start, m_end, buf.data()); to std::copy(m_start, m_end, buf.begin()); fix this problem.


warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.

I think turning off the warning like proposed on #453 before might be enough but probably not a clean solution.

@nlohmann
Copy link
Owner

Thanks for reporting! I had some headaches taking over the code with strcat/strlen, but it seemed more elegant compared to a manual search for the \0 byte. However, this manual search can be done in a for loop in this setting, so it shall be safe to replace the array<char, N> by a std::vector<char> or std::string with respective reservation of N bytes.

@prsyahmi
Copy link
Author

prsyahmi commented Feb 20, 2017

Since dealing with string here, In my opinion the std::string with reservation of N bytes approach is a better choice. There will be no need to call strcat/strcpy or do it manually since we got + operator and = operator. The strlen you mentioned isn't affected and still can be used, but switching to .length() is recommended.

There is only one usage of strlen on array data I found in latest commit

const auto data_end = m_buf.begin() + strlen(m_buf.data());

const bool value_is_int_like =
      std::none_of(m_buf.begin(), data_end, [](const char c)
      {
           return (c == '.' or c == 'e' or c == 'E');
      });

which then can be switched to .cbegin(), .cend() instead.

@TurpentineDistillery
Copy link

The rationale for using std::array<char, N> instead of a std::string in this context was to avoid heap allocations, which is the performance bottleneck.

@prsyahmi
Copy link
Author

Well both std::string and std::vector does heap allocation. So for performance critical, I think ignoring the warning worth it, since we control the input data ".", "-0.0" and "0.0".

@nlohmann nlohmann self-assigned this Feb 20, 2017
@nlohmann nlohmann added this to the Release 2.1.1 milestone Feb 20, 2017
@prsyahmi
Copy link
Author

prsyahmi commented Feb 20, 2017

Another solution for the warnings

#if defined(_MSC_VER)
#define JSON_STRCPY strcpy_s
#define JSON_STRCAT strcat_s
#define JSON_STROUT(out, buflen) out, buflen
#else
#define JSON_STRCPY std::strcpy
#define JSON_STRCAT std::strcat
#define JSON_STROUT(out, buflen) out
#endif

Then call like this JSON_STRCAT(JSON_STROUT(m_buf.data(), m_buf.size()), ".0");

and finally

#undef JSON_STRCAT
#undef JSON_STRCPY
#undef JSON_STROUT

What do you think?

@nlohmann
Copy link
Owner

I did some refactoring to avoid the unsafe calls, see 83a9c60. I combined a call to strlen and a std::none_of to a single for loop and unrolled stdcpy/ strcat to a sequence of assignments. What do you think?

@nlohmann
Copy link
Owner

@prsyahmi Could you please try with the most recent version?

@prsyahmi
Copy link
Author

prsyahmi commented Feb 20, 2017

The code looks good and it compiles fine here, no more warning and error 👍 I guess this can be closed now. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants