【问题标题】:free(): invalid pointer when using scanffree():使用 scanf 时指针无效
【发布时间】:2021-10-05 11:25:18
【问题描述】:

大家好,这是我的代码。 我不能使用 cin 和 getline() 所以我不得不使用 scanf。 它按预期读取所有值,但在输入最后一个值后它说:

free(): 无效指针 ./comp: line 8: 877 Aborted (core dumped) ./$BIN

无论如何,这里是代码。 帮助将不胜感激。

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;


int main() {
    // n -> amount of lines of code.
    // q -> amount of queries.
    int n, q;
    cin >> n >> q;

    // Handle source code Input.
    vector<string> v(n);
    for (unsigned i = 0; i < n; ++i)
    {
        cout << "i: " << i << endl;
        scanf("%s", &v[i]);
    }
    
    return 0;
}

【问题讨论】:

  • std::string 不能很好地与 scanf("%s 配合使用。这个想法到底是在哪里培养的?您说,“我不能使用 cin 和 getline()” - 因为...?也许我们可以通过展示您在这方面的尝试来解决那个问题,而不是把这只 X 兔子追到一个 Y 洞里。
  • %s 格式参数表示指向 char 数组的指针即将到来。 std::stringchar 数组复杂得多。另请注意,scanf 是一个 C 函数。它对 std::string 这样的 C++ 结构一无所知,而且几乎肯定会错误地使用它们。
  • 顺便说一下,在任何语言中,但尤其是在像 C++ 这样容易出错的语言中,您应该始终将警告设置为他们会去的。在 g++ 和 clang 中,您可以将 -Wall 传递给编译器以打开所有警告。如果你这样做了,你会从编译器那里得到一个解释这个问题的警告。
  • Silvio Mayolo 关于额外警告的评论的附录,它还有助于在编译时提高优化级别。为了优化代码,编译器必须仔细查看代码,而仔细查看可能会暴露编译器可能遗漏的潜在错误。

标签: c++ pointers vector


【解决方案1】:

scanf 设计用于处理字符缓冲区,而不是字符串。您可能想使用std::string(它更直观并且为您管理内存),所以scanf 不适合。有一个version of getline 可以与string 一起使用。

std::vector<std::string> v(n);
for (int i = 0; i < n; i++) {
  cout << "i: " << i << endl;
  std::getline(std::cin, v[i]);
}

【讨论】:

    【解决方案2】:

    scanf()%s 说明符需要一个指向 char[] 数组的指针,而不是 std::string 对象。通过直接读取 std::string 对象,您正在破坏其内部结构。

    所以,您需要:

    • 先读入char[],然后将其分配给您的std::string
    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int main() {
        // n -> amount of lines of code.
        // q -> amount of queries.
        int n, q;
        cin >> n >> q;
    
        // Handle source code Input.
        vector<string> v(n);
        char buf[256];
        for (unsigned i = 0; i < n; ++i)
        {
            cout << "i: " << i << endl;
            scanf("%255s", buf);
            v[i] = buf;
            /* or:
            int len = scanf("%255s", buf);
            v[i] = string(buf, len);
            */
        }
        
        return 0;
    }
    
    • 预先分配std::string的内部字符缓冲区,然后直接读入它(注意,这种方法仅保证在C++11及更高版本中工作,但在实践中通常也适用于早期版本中std::string大多数实现):
    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int main() {
        // n -> amount of lines of code.
        // q -> amount of queries.
        int n, q;
        cin >> n >> q;
    
        // Handle source code Input.
        vector<string> v(n);
        for (unsigned i = 0; i < n; ++i)
        {
            cout << "i: " << i << endl;
            v[i].resize(256);
            int len = scanf("%255s", &v[i][0]/* or: v[i].data() in C++17 and later */);
            v[i].resize(len);
        }
        
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-05
      • 2012-02-21
      • 1970-01-01
      • 2013-06-27
      • 2021-10-07
      • 2015-03-31
      • 2017-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多