简体   繁体   English

缓冲区溢出?

[英]Buffer is overrun?

I am trying to turn a vector of char* into an array of char pointer but I get this annoying error and I can't figure out what I'm doing wrong.我正在尝试将 char* 向量转换为 char 指针数组,但我收到了这个烦人的错误,我不知道我做错了什么。

char** Parse::toCommand(std::vector<char*> command) {
    char** array = new char* [command.size()];
    for (int i = 0; i < command.size(); i++) {
        array[i] = command[i];
    }

    return array;
}

I get this warning which causes my program to not run.我收到此警告,导致我的程序无法运行。

 Buffer overrun while writing to 'array':  the writable size is 'command.public: unsigned int __thiscall std::vector<char *,class std::allocator<char *> >::size(void)const ()*4' bytes, but '8' bytes might be written.

the char* is actually a c string of course. char* 当然实际上是一个 c 字符串。

The strings in the vector are pieces of a string that was cut up using strtok_s.向量中的字符串是使用 strtok_s 分割的字符串片段。 I got rid of the Null at the end of every string by converting each to a c str using string::copy() to get a non constant c string and using the constructor of std::string to get a regular string.我通过使用 string::copy() 将每个字符串转换为 c str 以获取非常量 c 来获取非常量 c I then popped the back to rid myself of the null.然后我弹出背面以摆脱 null。

My end goal is I want to have an array of c strings so that I can pass it to execvp()我的最终目标是我想要一个 c 字符串数组,以便我可以将它传递给 execvp()

for (int i = 0; i < exes.size(); i++) {  //Separate each executable and argument list into vector of char* and push that to 2d vector of char*

        char* arg = exes[i]; //arg = the entire string executable and arguments
        std::vector <char*> argV;

        char* place = NULL;

        ptr3 = strtok_s(arg, " ", &place);

        while (ptr3 != NULL) {

            if (*ptr3 == '"') {//if beginning of remaining char* begins with ", push char*
                std::string temp;
                temp.push_back(*ptr3);
                ptr3 = strtok_s(NULL, "\"", &place);
                temp.append(ptr3);
                temp.pop_back();
                temp.push_back('"');
                char* cstr = new char[temp.size()];
                temp.copy(cstr, temp.size(), 0);
                argV.push_back(cstr);
            }
            else if (*ptr3 == '#') {
                break;
            }
            else {
                std::string temp(ptr3);
                temp.pop_back();
                char* cstr = new char[temp.size()];
                temp.copy(cstr, temp.size(), 0);
                argV.push_back(cstr);
            }
            ptr3 = strtok_s(NULL, " ", &place);
        }

        argV.push_back(NULL);
        args.push_back(argV);
    }

    for (int i = 0; i < args.size(); i++) {
        char** command = this->toCommand(args[i]);
        commands[i] = new COM(command);
    }

argV is a vector<vector<char*>> and argV 是一个vector<vector<char*>>

To be clear: this warning is not from the compiler but it's from the Microsoft code analyzer.需要明确的是:此警告不是来自编译器,而是来自 Microsoft 代码分析器。

I made a complete example that reproduces the warning using Visual Studio 2019. There are no more strings, pointers to pointers and other poor design and the warning is still there.我做了一个使用 Visual Studio 2019 重现警告的完整示例。没有更多的字符串、指向指针的指针和其他糟糕的设计,并且警告仍然存在。

For me the code is correct and it's simply a bug in the Microsoft code analyzer, or the analyzer is over cautious.对我来说,代码是正确的,它只是 Microsoft 代码分析器中的一个错误,或者分析器过于谨慎。

#include <iostream>
#include <vector>

int* toCommand(std::vector<int> command)
{
  int* array = new int [command.size()];
  for (size_t i = 0; i < command.size(); i++) {
    array[i] = command[i];
  }

  return array;
}

int main()
{
  std::vector v{1,2,3};
  int* foo = toCommand(v);
  for (int i = 0; i < 3; i++)
    std::cout << foo[i] << "\n";
}

The warning comes from the Microsoft Code analyzer and it's also displayed directly in the IDE:警告来自 Microsoft 代码分析器,它也直接显示在 IDE 中:

在此处输入图像描述

This is the simplest example that shows the warning:这是显示警告的最简单示例:

int* Foo(int size)
{
  int* array = new int [size];
  array[1] = 1;  // with array[0] = 1; the warning goes away
  return array;
}

warning C6386: Buffer overrun while writing to 'array': the writable size is 'size*4' bytes, but '8' bytes might be written.警告 C6386:写入“array”时缓冲区溢出:可写大小为“size*4”字节,但可能写入“8”字节。

The problem is not in the code you are showing but somewhere else.问题不在于您显示的代码,而在于其他地方。 Your code allocates rooms for pointers and then assigns those pointers.您的代码为指针分配空间,然后分配这些指针。

The big question is however: did you really evaluate pros and cons of using char * to represent strings instead of std::string ?然而,最大的问题是:你真的评估过使用char *来表示字符串而不是std::string的优缺点吗? Looks aiming for troubles...看起来是在找麻烦...

Also your code already depends on std::vector , why using manually allocated char ** instead of a std::vector<std::string> ?此外,您的代码已经依赖于std::vector ,为什么要使用手动分配的char **而不是std::vector<std::string> With a char** the way you use it there is for example no way you can know how many pointers are there (there is no way to implement size() in a portable way).使用char**您使用它的方式,例如,您无法知道有多少指针(无法以可移植的方式实现size() )。

EDIT编辑

From comments it seems you need to call execvp .从评论看来,您需要调用execvp From the man page:从手册页:

The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. execv()、execvp() 和 execvpe() 函数提供了一个指向以 null 结尾的字符串的指针数组,这些字符串表示新程序可用的参数列表。 The first argument, by convention, should point to the filename associated with the file being executed.按照惯例,第一个参数应该指向与正在执行的文件关联的文件名。

The array of pointers must be terminated by a NULL pointer.指针数组必须由 NULL 指针终止。

Note the last phrase.注意最后一句话。 You need to have one extra pointer set to NULL so that the command can know where the list of strings terminates.您需要将一个额外的指针设置为 NULL,以便命令可以知道字符串列表的终止位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM