5

I am writing a C++ program that outputs data to a file, generates a python script and calls pyplot to make the plotting.

However, when I pass the arguments in terms of the pointers, it can be compiled properly, but cannot run. It returns error. When I use Xcode debug mode and execute it step by step, it gives correct result by chance but not always. Sometimes it also returns an error.

I doubt that it might be caused by some memory allocation problem, but I cannot identify what is exactly the problem.

My codes are as following:

1) main

#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) head file

#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 */

When it is ran, I get below error message

malloc: *** error for object 0x1002002e8: incorrect checksum for freed object - object was probably modified after being freed.
JRG
  • 4,037
  • 3
  • 23
  • 34
Einstein_is_Coding
  • 195
  • 1
  • 1
  • 4
  • are you trying to build for ios, may be have a look at this link https://stackoverflow.com/questions/19840671/malloc-error-incorrect-checksum-for-freed-object-object-was-probably-mod – Sachin Jul 27 '17 at 23:38
  • Mainly your code doesnt see any free call, can you please mention your platform – Sachin Jul 27 '17 at 23:39
  • [OT]: You should avoid to use `using namespace std;` especially in header. – Jarod42 Jul 28 '17 at 10:52
  • [OT]: you should mark `inline` the functions defined in header to be able to include your header in several cpp files. – Jarod42 Jul 28 '17 at 10:54

3 Answers3

4

You want to pass an array, so pass an actual array which can be sized at runtime (std::vector), not some random pointer that hopefully will be pointing to the first element of an array (and in this case, it doesn't)

Your mistake is using new double(x) instead of new double[x]. The former allocates a single double with a value equal to x, and the latter allocates an array of double of size x and returns a pointer to the first element, but, as I've said, you wouldn't have that problem at all had you actually used std::vector and not dabbled with pointers like the early 90s style (not to mention, you wouldn't have a memory leak had you used std::vector).

milleniumbug
  • 15,379
  • 3
  • 47
  • 71
  • There are reasons to avoid `vector`, but even then you should use a `unique_ptr` or something. Most of those reasons are performance overhead, which is completely dwarfed by using Python. – Daniel H Jul 27 '17 at 23:38
3

You're doing a few things which are not right or seem strange.

The code new double(nline) will allocate a single double with the value of nline, which doesn't seem what you intend. It looks like you intend to dynamically allocate an array of double. Actually from the code you've shown there's no reason you can't do a simple array as the size is known at compile time.

This code below:

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

Could be replaced with:

double np_list[nline];
double pack_fraction_np[nline];
MrJLP
  • 978
  • 6
  • 14
  • Best declaring `nline` as `constexpr` – Yuval Ben-Arie Jul 27 '17 at 23:34
  • That or `std::array` would be best *if* it’s going to stay a compile-time constant, but if it was just set that way for debugging it doesn’t really help. – Daniel H Jul 27 '17 at 23:40
  • Note that since `nline` is a function parameter, using `double np_list[nline];` relies on a non-standard gcc extension (VLAs). `std::vector np_list(nline);` will work reliably across all standard compliant C++ compilers. – milleniumbug Jul 27 '17 at 23:46
0

The following lines allocate a single double for np_list and pack_fraction_np:

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

As a result, when you will enter your loop, you will write data to invalid memory blocks. You have to use square brackets to define an array (I do not get any error; using clang++).

Consider to use the std::vectorclass. Here is an example (your example) with std::pair of double nested in a std::vector:

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;
}
Papipone
  • 1,083
  • 3
  • 20
  • 39