简体   繁体   English

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

[英]Segmentation fault from pointer error (simple...)

I have a function which returns a pointer to an array of doubles:我有一个函数,它返回一个指向双精度数组的指针:

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;
}

When I try to access the output by saving the array to a variable (in a different function), I get a segmentation fault when the program runs (but it compiles fine):当我尝试通过将数组保存到变量(在不同的函数中)来访问输出时,程序运行时出现分段错误(但它编译得很好):

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();
}

Running the program yields normal function until it tries to call centerOfMass .运行程序会产生正常的功能,直到它尝试调用centerOfMass

I've checked most possible solutions;我已经检查了大多数可能的解决方案; I think I just lack understanding on pointers and their scope in C++.我想我只是缺乏对 C++ 中的指针及其作用域的理解。 I'm seasoned in PHP so dealing with memory explicitly is problematic.我在 PHP 方面经验丰富,因此明确处理内存是有问题的。

Thank you kindly非常感谢你

I'm not sure about the type of system.atoms .我不确定system.atoms的类型。 If it's a STL container like std::vector , the condition part of the for loop inside function centerOfMass is wrong.如果它是像std::vector这样的 STL 容器,则函数centerOfMass for循环的条件部分是错误的。

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

should be应该

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

PS1: You can use Range-based for loop (since C++11) to avoid such kind of problem. PS1:您可以使用基于范围的 for 循环(C++11 起)来避免此类问题。

PS2: You didn't delete[] the dynamically allocated arrays; PS2:你没有delete[]动态分配的数组; Consider about using std::vector , std::array , or std::unique_ptr instead, they're designed to help you to avoid such kind of issues.考虑使用std::vectorstd::arraystd::unique_ptr ,它们旨在帮助您避免此类问题。

In addition to the concerns pointed out by songyuanyao, the usage of the function in writeXYZ() causes a memory leak.除了writeXYZ()指出的问题外, writeXYZ()函数的使用会导致内存泄漏。

To see this, note that centerOfMass() does (with extraneous details removed)要看到这一点,请注意centerOfMass()确实(删除了无关的细节)

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

and writeXYZ() does (note that I've changed comments to reflect what is actually happening, as distinct from your comments on what you thought was happening)writeXYZ()确实(请注意,我已经更改了评论以反映实际发生的事情,这与您对您认为正在发生的事情的评论不同)

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

// output to myfile

If writeXYZ() is being called multiple times, then the three double s will be leaked every time, EVEN IF, somewhere, delete [] comfinal is subsequently performed.如果writeXYZ()调用writeXYZ() ,那么每次都会泄漏三个double ,即使在某处,随后执行delete [] comfinal If this function is called numerous times (for example, in a loop) eventually the amount of memory leaked can exceed what is available, and subsequent allocations will fail.如果多次调用此函数(例如,在循环中),最终泄漏的内存量可能会超过可用量,随后的分配将失败。

One fix of this problem is to change the relevant part of writeXYZ() to此问题的一种解决方法是将writeXYZ()的相关部分更改为

double* comfinal = centerOfMass(system);

// output to myfile

delete [] comfinal;    // eventually

Introducing std::unique_ptr in the above will alleviate the symptoms, but that is more a happy accident than good logic in the code (allocating memory only to discard it immediately without having used it is rarely good technique).在上面引入std::unique_ptr将缓解症状,但这比代码中的良好逻辑更像是一个快乐的意外(分配内存只是为了立即丢弃它而不使用它很少是好的技术)。

In practice, you are better off using standard containers ( std::vector , etc) and avoid using operator new at all.在实践中,最好使用标准容器( std::vector等)并完全避免使用 operator new But they still require you to keep within bounds.但他们仍然要求你保持在界限内。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM