簡體   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