C++函数中的指针参数

5
我正在编写一份C++程序,用于将数据输出到文件中,生成一个Python脚本并调用“pyplot”进行绘图。
然而,当我使用指针作为参数来传递数据时,程序可以被正确编译,但无法运行。它会返回错误。当我使用Xcode的调试模式逐步执行程序时,有时候它会偶尔地给出正确的结果,但并非总是如此。有时它也会返回错误。
我怀疑这可能是由于一些内存分配问题造成的,但我无法确定具体出了什么问题。
我的代码如下所示:
1)主函数
#include <iostream>
#include <stdlib.h>
#include <cmath>
#include "PyCPlot.h"

using namespace std;

double pi = 3.1415926;

int main(int argc, const char * argv[]) {

    int nline = 100;

    double * np_list = new double(nline);
    double * pack_fraction_np = new double (nline);

    for (int i=0; i<nline; i++){
        np_list[i] = double(i)/double(nline)*2*pi;
        pack_fraction_np[i] = cos(np_list[i]);
    }

    PyCPlot_data_fout("RandomPacking", nline, np_list, pack_fraction_np);
    PyCPlot_pythonscript("RandomPacking", "Random Packing");
    PyCPlot_pyplot("RandomPacking", "Random Packing");

    return 0;
}

2) 头文件

#ifndef PyCPlot_h
#define PyCPlot_h

#include <iostream>
#include <cmath>
#include <fstream>
#include <string>
#include <stdlib.h>

using namespace std;


int PyCPlot_data_fout(string datafilename, int nline, double * x, double *y){
    ofstream fout;
    fout.open(datafilename+".txt");
    fout << nline << endl;
    for (int i=0; i<nline; i++){
        fout << x[i] << "  " << y[i] << endl;
    }
    fout.close();
    return 0;
}

int PyCPlot_pythonscript(string datafilename, string plttitle){

    string strhead = "import numpy as np\nimport matplotlib.pyplot as plt\n";
    string strpltfig = "plt.figure()\n";
    string strpltplt = "plt.plot(xlist, ylist)\n";
    string strplttit = "plt.title('"+plttitle+"')\n";
    string strpltshw = "plt.show()\n";

    string strfileopen ="f = open('"+datafilename+".txt', 'r')\n";
    string strreadline ="size = map(int, f.readline().split())\n";
    string strpltlist ="xlist = np.zeros((size))\nylist = np.zeros((size))\n";
    string strfor = "for i in range(size[0]):\n    xlist[i], ylist[i] = map(float, f.readline().split())\n";

    ofstream pyout;
    pyout.open("PyCPlot_"+datafilename+".py");
    pyout << strhead << strfileopen << strreadline << strpltlist << strfor;
    pyout << strpltfig << strpltplt << strplttit << strpltshw;
    pyout.close();
    return 0;
}

int PyCPlot_pyplot(string datafilename, string plttitle){

    string strsystemsh ="source ~/.bashrc; python PyCPlot_"+datafilename+".py";
    system(strsystemsh.c_str());

    return 0;
}

#endif /* PyCPlot_h */

当它运行时,我会收到以下错误消息。
malloc: *** error for object 0x1002002e8: incorrect checksum for freed object - object was probably modified after being freed.

你是否正在尝试构建iOS应用?也许可以查看这个链接:https://dev59.com/yWIj5IYBdhLWcg3w04Xd - Sachin
主要是你的代码没有看到任何免费通话,请您提供一下您使用的平台 - Sachin
[OT]:你应该避免在头文件中使用 using namespace std; - Jarod42
[OT]: 你应该在头文件中定义的函数上标记为 inline,以便能够将头文件包含在多个cpp文件中。 - Jarod42
3个回答

4
你想传递一个数组,因此请传递一个可以在运行时调整大小的实际数组(std::vector),而不是一些随机指针,希望它会指向数组的第一个元素(在这种情况下,它并没有指向)。你的错误在于使用new double(x)而不是new double[x]。前者分配一个值等于x的单个double,后者分配一个大小为x的double数组并返回指向第一个元素的指针,但是,正如我所说,如果你真正使用std::vector而不是涉及指针,那么你根本不会有这个问题(更不用说,如果你使用std::vector,你就不会有内存泄漏问题)。

有一些避免使用vector的理由,但即使如此,你应该使用unique_ptr<T[]>或类似的东西。大多数这些理由都是性能开销,而使用Python则完全可以弥补这些开销。 - Daniel H

3
你正在做一些不正确或奇怪的事情。
代码new double(nline)将分配一个值为nline的单个double,这似乎不是你想要的。 看起来你的意图是动态分配一个double数组。实际上,从你展示的代码来看,没有理由不使用简单的数组,因为大小在编译时已知。
以下是代码:
double * np_list = new double(nline);
double * pack_fraction_np = new double (nline);

可以替换为:

double np_list[nline];
double pack_fraction_np[nline];

最佳做法是将 nline 声明为 constexpr - Yuval Ben-Arie
如果它将保持为编译时常量,那么最好使用std::array<double, nline>,但是如果仅仅是为了调试而设置的,那么这并没有真正帮助到你。 - Daniel H
请注意,由于nline是函数参数,使用double np_list [nline];依赖于非标准的gcc扩展(VLAs)。在所有符合标准的C++编译器中,std::vector<double> np_list(nline);将可靠地工作。 - milleniumbug

0
下面的代码为`np_list`和`pack_fraction_np`分配了一个双精度浮点数:
double * np_list = new double(nline);
double * pack_fraction_np = new double (nline);

因此,当您进入循环时,您将向无效的内存块写入数据。您必须使用方括号来定义数组(使用clang++时我没有收到任何错误)。

考虑使用std::vector类。这是一个示例(您的示例),其中包含嵌套在std::vector中的doublestd::pair

PyCPlot.h

#ifndef PyCPlot_h
#define PyCPlot_h

#include <iostream>
#include <cmath>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <vector>
#include <utility>

using namespace std;

int PyCPlot_data_fout(string datafilename, std::vector<std::pair<double, double>>& v){
    ofstream fout;
    fout.open(datafilename+".txt");
    fout << v.size() << endl;
    for (int i=0; i < v.size(); i++){
        fout << v[i].first << "  " << v[i].second << endl;
    }
    fout.close();
    return 0;
}

int PyCPlot_pythonscript(string datafilename, string plttitle){

    string strhead = "import numpy as np\nimport matplotlib.pyplot as plt\n";
    string strpltfig = "plt.figure()\n";
    string strpltplt = "plt.plot(xlist, ylist)\n";
    string strplttit = "plt.title('"+plttitle+"')\n";
    string strpltshw = "plt.show()\n";

    string strfileopen ="f = open('"+datafilename+".txt', 'r')\n";
    string strreadline ="size = map(int, f.readline().split())\n";
    string strpltlist ="xlist = np.zeros((size))\nylist = np.zeros((size))\n";
    string strfor = "for i in range(size[0]):\n    xlist[i], ylist[i] = map(float, f.readline().split())\n";

    ofstream pyout;
    pyout.open("PyCPlot_"+datafilename+".py");
    pyout << strhead << strfileopen << strreadline << strpltlist << strfor;
    pyout << strpltfig << strpltplt << strplttit << strpltshw;
    pyout.close();
    return 0;
}

int PyCPlot_pyplot(string datafilename, string plttitle){

    string strsystemsh ="source ~/.bashrc; python PyCPlot_"+datafilename+".py";
    system(strsystemsh.c_str());

    return 0;
}

#endif /* PyCPlot_h */

PyCPlot.cpp

#include <iostream>
#include <stdlib.h>
#include <cmath>
#include "PyCPlot.h"

using namespace std;

double pi = 3.1415926;

int main(int argc, const char * argv[]) {

    int nline = 100;
    std::vector<std::pair<double, double>> v;
    v.reserve(nline);

    double a;
    for (int i=0; i < nline; i++){
        a = double(i)/double(nline)*2*pi;
        v.push_back(std::make_pair(a, cos(a)));
    }

    PyCPlot_data_fout("RandomPacking", v);
    PyCPlot_pythonscript("RandomPacking", "Random Packing");
    PyCPlot_pyplot("RandomPacking", "Random Packing");

    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接