繁体   English   中英

缓冲区溢出?

[英]Buffer is overrun?

我正在尝试将 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;
}

我收到此警告,导致我的程序无法运行。

 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.

char* 当然实际上是一个 c 字符串。

向量中的字符串是使用 strtok_s 分割的字符串片段。 我通过使用 string::copy() 将每个字符串转换为 c str 以获取非常量 c 来获取非常量 c 然后我弹出背面以摆脱 null。

我的最终目标是我想要一个 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 是一个vector<vector<char*>>

需要明确的是:此警告不是来自编译器,而是来自 Microsoft 代码分析器。

我做了一个使用 Visual Studio 2019 重现警告的完整示例。没有更多的字符串、指向指针的指针和其他糟糕的设计,并且警告仍然存在。

对我来说,代码是正确的,它只是 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";
}

警告来自 Microsoft 代码分析器,它也直接显示在 IDE 中:

在此处输入图像描述

这是显示警告的最简单示例:

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

警告 C6386:写入“array”时缓冲区溢出:可写大小为“size*4”字节,但可能写入“8”字节。

问题不在于您显示的代码,而在于其他地方。 您的代码为指针分配空间,然后分配这些指针。

然而,最大的问题是:你真的评估过使用char *来表示字符串而不是std::string的优缺点吗? 看起来是在找麻烦...

此外,您的代码已经依赖于std::vector ,为什么要使用手动分配的char **而不是std::vector<std::string> 使用char**您使用它的方式,例如,您无法知道有多少指针(无法以可移植的方式实现size() )。

编辑

从评论看来,您需要调用execvp 从手册页:

execv()、execvp() 和 execvpe() 函数提供了一个指向以 null 结尾的字符串的指针数组,这些字符串表示新程序可用的参数列表。 按照惯例,第一个参数应该指向与正在执行的文件关联的文件名。

指针数组必须由 NULL 指针终止。

注意最后一句话。 您需要将一个额外的指针设置为 NULL,以便命令可以知道字符串列表的终止位置。

暂无
暂无

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

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