0

I am attempting to send a command that runs a specific python script: however, whenever the program reaches the execution line, this occurs:

Unhandled exception at 0x69bd1f16 in GameServer.exe: 0xC0000005: Access violation reading location 0x46f520ca.

The program stops resonding and crashes. Here is the method in question:

void ScriptManager::runScript(std::string scriptName, std::string args[])
{
    std::string py = "python " + scriptName;
    std::cout << py << std::endl;
    for(int i = 0; i < args->length(); i++)
    {
        py += " " + args[i];
        std::cout << py << std::endl;
    }
    std::cout << py << std::endl;

    std::system(py.c_str());

}

This calls the above function:

void DBFactory::dbRegisterUser(std::string username, std::string password)
{
    ScriptManager script;
    std::string data[] = {username, password};

    script.runScript("Python.py", data);
}

The script does not run, as far as I know. I can also post the script if it would help.

9
  • 1
    The loop over args->length() looks wrong. That is the length of the first string, i.e. args[0]. Can you show the code that calls this function? Commented Jun 1, 2014 at 18:28
  • Yes. I've updated the post with the function. Commented Jun 1, 2014 at 18:32
  • You will need to pass the length of the array to the function, or use a function template that can deduce the array's length information. See stackoverflow.com/questions/1328223/…. Commented Jun 1, 2014 at 18:40
  • Hm... It appears that the command is being constructed correctly (python Python.py arg1 arg2), but the execution is throwing the error. Unless I'm misunderstanding what you're saying? Commented Jun 1, 2014 at 18:53
  • args->length() is the length of args[0], i.e. username. Not the number of elements in args. Commented Jun 1, 2014 at 18:55

1 Answer 1

1

This is the problem:

for (int i = 0; i < args->length(); i++)
{
    py += " " + args[i];
    std::cout << py << std::endl;
}

args->length() is equivalent to args[0].length(); i.e. you're taking the length of the first string in the array and using that as an index. After two iterations pass, you're going to access past the end of the array. The best solutions are(all examples are UNTESTED):

  1. Use an std::array(C++11 only):

    void DBFactory::dbRegisterUser(std::string username, std::string password)
    {
        ScriptManager script;
    
        script.runScript("Python.py", {username, password});
    }
    
    void ScriptManager::runScript(std::string scriptName, std::array<std::string, 2> args)
    {
        std::string py = "python " + scriptName;
        std::cout << py << std::endl;
        for (std::string s : args)
        {
                py += " " + s;
                std::cout << py << std::endl;
        }
        std::cout << py << std::endl;
    
        std::system(py.c_str());
    }
    
  2. Use an std::vector(the example uses C++03):

    void DBFactory::dbRegisterUser(std::string username, std::string password)
    {
        ScriptManager script;
        int tmp[2] = {username, password};
    
        script.runScript("Python.py", std::vector<std::string>(&tmp[0], &tmp[0]+2));
    }
    
    void ScriptManager::runScript(std::string scriptName, std::vector<std::string> args)
    {
        std::string py = "python " + scriptName;
        std::cout << py << std::endl;
        for(std::vector<std::string>::iterator it = args.begin(); it != args.end(); it++)
        {
            py += " " + *it;
            std::cout << py << std::endl;
        }
        std::cout << py << std::endl;
    
        std::system(py.c_str());
        }
    
  3. Pass the array size as a parameter:

    void DBFactory::dbRegisterUser(std::string username, std::string password)
    {
        ScriptManager script;
    
        script.runScript("Python.py", {username, password}, 2);
    }
    
    void ScriptManager::runScript(std::string scriptName, std::string args[], int size)
    {
        std::string py = "python " + scriptName;
        std::cout << py << std::endl;
        for(int i=0; i<size; i++)
        {
            py += " " + args[i];
            std::cout << py << std::endl;
        }
        std::cout << py << std::endl;
    
        std::system(py.c_str());
    }
    

I personally prefer example 1 and would avoid example 3 like the plague. Example 2 works well but probably isn't as fast as example 1.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.