2
votes

After I ran the code, I got errors listed below. How can I replace strcpy with strcpy_s? Thanks for any help. And also when I tried replacing strcpy with strcpy_s directly, it said namespace "std" has no member "strcpy_s".

Severity Code Description Project File Line Suppression State Error C4996 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. Nuitrack_project e:\nuitracksdk\nuitrack\include\nuitrack\types\issue.h 71

Severity Code Description Project File Line Suppression State Error C4996 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. Nuitrack_project e:\nuitracksdk\nuitrack\include\nuitrack\types\issue.h 81

#ifndef NUITRACK_ISSUE_H_
#define NUITRACK_ISSUE_H_

#include <memory>
#include <string>
#include<cstring>

namespace tdv
{
namespace nuitrack
{
/**
 * @ingroup CommonElements_group
 * @brief Describes an issue identifier.
 */
enum IssueId
{
    NONE_ISSUE = 0,
    FRAME_BORDER_ISSUE = 1,
    OCCLUSION_ISSUE = 2,
    SENSOR_ISSUE = 3
};

/**
 * @ingroup CommonElements_group
 * @brief Stores general information about a issue.
 * 
 * Parent class of all issue classes.
 */
class Issue
{
public:
     /**
     * @brief Smart pointer to access the Issue instance.
     */
    typedef std::shared_ptr<Issue> Ptr;

    /**
     * @brief Returns the issue type as a string.
     */
    static std::string getType()
    {
        static std::string _type = "Issue";
        return _type;
    }

    /**
     * @brief Returns the issue name.
     */
    virtual std::string getName() const
    {
            return std::string(_name);
    }

    /**
     * @brief Returns the issue identifier.
     */
    IssueId getId()
    {
        return _id;
    }

    /**
     * @brief Constructs a default issue.
     */
    Issue() :
        _id(NONE_ISSUE)
   {
        std::string name = "Issue";
        _name = new char[name.length() + 1];
        std::strcpy(_name, name.c_str());
    }

    /**
     * @brief Constructs an issue object from its identifier and name.
     */
    Issue(IssueId id, const std::string &name) :
        _id(id)
    {
        _name = new char[name.length() + 1];
        std::strcpy(_name, name.c_str());
    }

    virtual ~Issue()
    {
        deleteString();
    }

    /**
     * Release the memory occupied by the string representation of the name.
     */
    void deleteString()
    {
        if(_name)
        {
            delete[] _name;
            _name = NULL;
        }
    }

    /**
     * @brief Copy constructor.
     */
    Issue(const Issue& issue)
    {
        copyIssue(issue);
    }

    /**
     * @brief Overloaded copy assignment operator.
     */
    void operator=(const Issue& issue)
    {
        copyIssue(issue);
    }

protected:
    /** @warning For internal use only. */
    IssueId _id;
    /** @warning For internal use only. */
    char* _name;

private:
    void copyIssue(const Issue& issue)
    {
        _id = issue._id;

        uint32_t nameSize = 0;
        while(issue._name[nameSize] != '\0')
            nameSize++;

        _name = new char[nameSize + 1];
        for(uint32_t i = 0; i <= nameSize; i++)
            _name[i] = issue._name[i];
    }
};

} /* namespace nuitrack */
} /* namespace tdv */

#endif /* NUITRACK_ISSUE_H_ */
1
Why are you using a mixture of std::string and raw pointers?Retired Ninja
Given that you know the size of the destination is large enough I don't really see the advantage of strcpy_s except it gives you one more chance to make a mistake.Galik
Other than that, strcpy_s is only part of the C libraries, not the C++ versions so you can't prefix with the std:: namespace.Galik
It would be best to just disable those warnings, strcpy_s does not add any real safety and maybe even increases the scope for errorsM.M

1 Answers

4
votes

strcpy_s ("s" stands for "safe") allows you to specify the size of your destination buffer. std::strcpy doesn't do this, thus allowing you to write past the end of your destination buffer if your source is too long, with bad effects.

In your first case above, try this:

_name = new char[name.length() + 1];
strcpy_s(_name, name.length() + 1, name.c_str());

Simply replacing strcpy with strcpy_s doesn't work for 2 reasons: 1) strcpy_s takes another parameter (the length of the destination buffer) 2) strcpy_s is not part of std, i.e. the std namespace doesn't contain a declaration of strcpy_s

So try adding the extra parameter, and replacing "std:strcpy" with just "strcpy_s"

If you're in an IDE like Visual Stdio, you can often right-click on a term like "strcpy_s" select something like "Go to Declaration" from the context menu that appears, and get some quick information about the term.

  • Bob

Note: If you're new to the mechanics of compiling and building C/C++ programs, maybe it's worth explaining the error message. That message is telling you that if you want to use the traditional "unsafe" c calls such as strcpy, you can do so by adding _CRT_SECURE_NO_WARNINGS to the preprocessor definitions in your build system. This can be a #define prior to the inclusion of the relevant headers, or it can be an entry somewhere in your IDE. If you enter that definition, your compiler will let you use std::strcpy without complaint.