指针错误导致分段错误(简单...)

时间:2017-01-21 03:03:00

标签: c++ arrays function pointers

我有一个函数,它返回一个指向双精度数组的指针:

double * centerOfMass(System &system) {
        long unsigned int size = system.atoms.size();

        double x_mass_sum=0.0; double y_mass_sum=0.0; double z_mass_sum=0.0; double mass_sum=0.0;

        for (int i=0; i<=size; i++) {
                double atom_mass = system.atoms[i].m;
                mass_sum += atom_mass;

                x_mass_sum += system.atoms[i].pos["x"]*atom_mass;
                y_mass_sum += system.atoms[i].pos["y"]*atom_mass;
                z_mass_sum += system.atoms[i].pos["z"]*atom_mass;
        }

        double comx = x_mass_sum/mass_sum;
        double comy = y_mass_sum/mass_sum;
        double comz = z_mass_sum/mass_sum;

        double* output = new double[3];  // <-------- here is output
        output[0] = comx*1e10; // convert all to A for writing xyz
        output[1] = comy*1e10;
        output[2] = comz*1e10;
        return output;
}

当我尝试通过将数组保存到变量(在不同的函数中)来访问输出时,程序运行时会出现分段错误(但编译正常):

void writeXYZ(System &system, string filename, int step) {

        ofstream myfile;
        myfile.open (filename, ios_base::app);
        long unsigned int size = system.atoms.size();
        myfile << to_string(size) + "\nStep count: " + to_string(step) + "\n";

        for (int i = 0; i < size; i++) {
                myfile << system.atoms[i].name;
                myfile <<  "   ";
                myfile << system.atoms[i].pos["x"]*1e10;
                myfile <<  "   ";
                myfile << system.atoms[i].pos["y"]*1e10;
                myfile <<  "   ";
                myfile << system.atoms[i].pos["z"]*1e10;
                myfile << "\n";
        }

        // get center of mass
        double* comfinal = new double[3]; // goes fine
        comfinal = centerOfMass(system); // does NOT go fine..
        myfile << "COM   " << to_string(comfinal[0]) << "   " << to_string(comfinal[1]) << "   " << to_string(comfinal[2]) << "\n";

        myfile.close();
}

运行程序会产生正常函数,直到它尝试调用centerOfMass

我检查了大多数可能的解决方案;我想我只是缺乏对C ++中指针及其范围的理解。我在PHP中经验丰富,因此明确处理内存是有问题的。

谢天谢地

2 个答案:

答案 0 :(得分:4)

我不确定system.atoms的类型。如果它是std::vector之类的STL容器,则函数for内的centerOfMass循环的条件部分是错误的。

long unsigned int size = system.atoms.size();
for (int i=0; i<=size; i++) {

应该是

long unsigned int size = system.atoms.size();
for (int i=0; i<size; i++) {

PS1:您可以使用Range-based for loop (since C++11)来避免此类问题。

PS2:你没有delete[]动态分配的数组;考虑使用std::vectorstd::arraystd::unique_ptr代替它们,它们旨在帮助您避免此类问题。

答案 1 :(得分:1)

除了songyuanyao指出的问题之外,writeXYZ()中函数的使用会导致内存泄漏。

要查看此内容,请注意centerOfMass()执行此操作(删除了无关的详细信息)

 double* output = new double[3];  // <-------- here is output
 // assign values to output
 return output;

writeXYZ()确实如此(请注意,我更改了评论以反映实际发生的情况,与您对您认为发生的事情的评论截然不同)

double* comfinal = new double[3]; //  allocate three doubles
comfinal = centerOfMass(system); //   lose reference to them

// output to myfile

如果多次调用writeXYZ(),则每次都会泄漏三个double,即使在某处,delete [] comfinal随后也会被执行。如果多次调用此函数(例如,在循环中),最终泄漏的内存量可能超过可用内存量,后续分配将失败。

此问题的一个解决方法是将writeXYZ()的相关部分更改为

double* comfinal = centerOfMass(system);

// output to myfile

delete [] comfinal;    // eventually

在上面介绍std::unique_ptr将缓解症状,但这比代码中的良好逻辑更令人高兴(仅分配内存以立即丢弃它而不使用它很少是好技术)。

实际上,最好使用标准容器(std::vector等)并避免使用运算符new。但他们仍然要求你保持在一定范围内。