return 语句之前/期间的 C 分段错误

发布于 2024-09-05 08:59:32 字数 1598 浏览 2 评论 0原文

我在 return 语句之前打印要返回的值,并告诉我的代码打印在函数调用之后立即返回的值。但是,在第一个打印语句之后和第二个打印语句之前,我遇到了分段错误(还值得注意的是,这种情况总是发生在第三次调用该函数时;从来没有第一次或第二次,也从来没有第四次或更晚)。我尝试打印出我正在处理的所有数据,以查看我的代码的其余部分是否做了一些可能不应该做的事情,但到目前为止我的数据看起来不错。这是这个函数:

int findHydrogen(struct Amino* amino, int nPos, float* diff, int totRead) {

    struct Atom* atoms;
    int* bonds;
    int numBonds;
    int i;
    int retVal;
    int numAtoms;

    numAtoms = (*amino).numAtoms;

    atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
    atoms = (*amino).atoms;

    numBonds = atoms[nPos].numBonds;

    bonds = (int *) malloc(sizeof(int) * numBonds);
    bonds = atoms[nPos].bonds;

    for(i = 0; i < (*amino).numAtoms; i++)
        printf("ATOM\t\t%d  %s\t0001\t%f\t%f\t%f\n", i + 1, atoms[i].type, atoms[i].x, atoms[i].y, atoms[i].z);

    for(i = 0; i < numBonds; i++) 
        if(atoms[bonds[i] - totRead].type[0] == 'H') {
            diff[0] = atoms[bonds[i] - totRead].x - atoms[nPos].x;
            diff[1] = atoms[bonds[i] - totRead].y - atoms[nPos].y;
            diff[2] = atoms[bonds[i] - totRead].z - atoms[nPos].z;

            retVal = bonds[i] - totRead;

            bonds = (int *) malloc(sizeof(int));
            free(bonds);

            atoms = (struct Atom *) malloc(sizeof(struct Atom));
            free(atoms);

            printf("2 %d\n", retVal);

            return retVal;
        }
}

正如我之前提到的,我运行它的前两次它工作正常,第三次它打印正确的 retVal 值,然后在到达我调用该函数的位置之前在某处出现段错误,我这样做:

hPos = findHydrogen((&aminoAcid[i]), nPos, diff, totRead);
printf("%d\n", hPos);

I print the value that I'm returning right before my return statement, and tell my code to print the value that was returned right after the function call. However, I get a segmentation fault after my first print statement and before my second (also interesting to note, this always happens on the third time the function is called; never the first or the second, never fourth or later). I tried printing out all of the data that I'm working on to see if the rest of my code was doing something it maybe shouldn't, but my data up to that point looks fine. Here's the function:

int findHydrogen(struct Amino* amino, int nPos, float* diff, int totRead) {

    struct Atom* atoms;
    int* bonds;
    int numBonds;
    int i;
    int retVal;
    int numAtoms;

    numAtoms = (*amino).numAtoms;

    atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
    atoms = (*amino).atoms;

    numBonds = atoms[nPos].numBonds;

    bonds = (int *) malloc(sizeof(int) * numBonds);
    bonds = atoms[nPos].bonds;

    for(i = 0; i < (*amino).numAtoms; i++)
        printf("ATOM\t\t%d  %s\t0001\t%f\t%f\t%f\n", i + 1, atoms[i].type, atoms[i].x, atoms[i].y, atoms[i].z);

    for(i = 0; i < numBonds; i++) 
        if(atoms[bonds[i] - totRead].type[0] == 'H') {
            diff[0] = atoms[bonds[i] - totRead].x - atoms[nPos].x;
            diff[1] = atoms[bonds[i] - totRead].y - atoms[nPos].y;
            diff[2] = atoms[bonds[i] - totRead].z - atoms[nPos].z;

            retVal = bonds[i] - totRead;

            bonds = (int *) malloc(sizeof(int));
            free(bonds);

            atoms = (struct Atom *) malloc(sizeof(struct Atom));
            free(atoms);

            printf("2 %d\n", retVal);

            return retVal;
        }
}

As I mentioned before, it works fine the first two times I run it, the third time it prints the correct value of retVal, then seg faults somewhere before it gets to where I called the function, which I do as:

hPos = findHydrogen((&aminoAcid[i]), nPos, diff, totRead);
printf("%d\n", hPos);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

蹲墙角沉默 2024-09-12 08:59:32

返回时的分段错误通常表示堆栈损坏。

A segmentation fault while returning is normally an indication of a mangled stack.

谈情不如逗狗 2024-09-12 08:59:32

很难从这段代码中猜测错误出在哪里(这里几乎每一行代码都可能存在错误) - 可能你在某个地方有缓冲区溢出,但是如果你在 *nix 上,请在下面运行你的程序valgrind,您应该能够很快找到错误。

但这些行看起来很奇怪:

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
atoms = (*amino).atoms;

当您丢弃 malloc 返回的指针时,您正在泄漏内存。与bond 相同,并且在 for 循环中再次出现相同的情况。

It's not easy to guess where the error is from this code(there's a potential for bug in just about every line of code here) - likely you have a buffer overrun somewhere, however if you're on a *nix , run your program under valgrind, you should be able to find the error rather quickly.

These lines look odd though:

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
atoms = (*amino).atoms;

You're leaking memory, as you discard the pointer returned by malloc. Same thing with bonds, and same thing over again inside your for loop.

春风十里 2024-09-12 08:59:32

编辑好吧,你左右泄漏内存,但并不完全按照我的想法。固定顺序如下:

具体来说,当您执行以下操作时:

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms); // 1
atoms = (*amino).atoms; // 2
// ...
atoms = (struct Atom *) malloc(sizeof(struct Atom)); // 3
free(atoms); // 4

发生的情况是您在步骤 (1) 中分配一些内存并将地址放入 atoms 中。然后,您丢弃该地址,并将原子指向 (2) 中的氨基结构内部的一部分。然后,您分配一个带有单个原子的第二个指针。最后,您调用free。您以同样的方式对待债券。您的意思可能是这样的:

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms); // 1
memcpy(atoms, (*amino).atoms, sizeof(struct Atom) * numAtoms); // 2
// ...
// delete 3
free(atoms); // 4

请注意,如果 Atom 有任何指针组件,您可能需要执行 for 循环并单独复制原子及其内容,然后您必须单独复制它们>返回点免费。

...或者如果您只想从结构中读取原子数据,则可能只是这样:

atoms = (*amino).atoms; // delete 1, 3, 4 entirely and just read directly from the structure

有关 diff 中的空间量和其他问题的其他答案可能也值得研究。

编辑:修复了调用顺序以匹配代码示例。

EDIT Well, you're leaking memory left and right, but not quite in the way I was thinking. Fixed sequence below:

Specifically, when you do:

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms); // 1
atoms = (*amino).atoms; // 2
// ...
atoms = (struct Atom *) malloc(sizeof(struct Atom)); // 3
free(atoms); // 4

What is happening is that you are allocating some memory and putting the address in atoms in step(1). Then, you toss away that address and instead point atoms at part of the inside of your amino structure in (2). Then you allocate a second pointer with a single atom. Finally, you call free on that. You treat bonds the same way. You probably mean something like this:

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms); // 1
memcpy(atoms, (*amino).atoms, sizeof(struct Atom) * numAtoms); // 2
// ...
// delete 3
free(atoms); // 4

Note that if an Atom has any pointer components you might want to do a for loop and copy the atoms individually along with their contents, which you would then have to individually free at the return point.

...or maybe just this if you are only wanting to read the atoms data from the structure:

atoms = (*amino).atoms; // delete 1, 3, 4 entirely and just read directly from the structure

Other answers talking about the amount of space in diff and other issues are probably also worth investigating.

EDIT: fixed the sequence of calls to match the code sample.

小忆控 2024-09-12 08:59:32

这里有很多问题。

我注意到的第一件事是您泄漏了内存(您在 (struct Atom *) malloc(sizeof(struct Atom) * numAtoms) 处分配了一些内存,然后用氨基结构);您可以使用 (int *) malloc(sizeof(int) * numBonds); 执行相同的操作。

其次,您没有对表达式 Bonds[i] - totRead 进行边界检查。

第三,我认为这就是你崩溃的地方,你在这里覆盖你的原子指针:atoms = (struct Atom *) malloc(sizeof(struct Atom)); free(atoms); 这使得原子指向无效内存。

There are a lot of things wrong here.

The first thing I notice is that you're leaking memory (you allocate some memory at (struct Atom *) malloc(sizeof(struct Atom) * numAtoms), then overwrite the pointer with the pointer in the amino structure); you do the same thing with (int *) malloc(sizeof(int) * numBonds); .

Second, you're not bounds-checking the expression bonds[i] - totRead.

Third, and I think this is where you're crashing, you overwrite your atoms pointer here: atoms = (struct Atom *) malloc(sizeof(struct Atom)); free(atoms); which leaves atoms pointing to invalid memory.

囍孤女 2024-09-12 08:59:32

下面是对部分代码的小重写,以演示内存泄漏:

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms); // allocating new struct
atoms = (*amino).atoms; // overriding the pointer with pointer to a struct allocated in the caller
//...
for (some counter on atoms)
{
    if (something that succeeds)
    {
      atoms = (struct Atom *) malloc(sizeof(struct Atom)); // overwrite the pointer yet again with newly allocated struct
      free(atoms); // free the last allocated struct
      // at this point atoms points to invalid memory, so on the next iteration of the outer for it'll crash
    }
}

语句 bonds[i] - totRead 也有可能超出 atoms[] 范围,这可能是段错误。

Here's a small rewrite of parts of your code to demonstrate the memory leaks:

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms); // allocating new struct
atoms = (*amino).atoms; // overriding the pointer with pointer to a struct allocated in the caller
//...
for (some counter on atoms)
{
    if (something that succeeds)
    {
      atoms = (struct Atom *) malloc(sizeof(struct Atom)); // overwrite the pointer yet again with newly allocated struct
      free(atoms); // free the last allocated struct
      // at this point atoms points to invalid memory, so on the next iteration of the outer for it'll crash
    }
}

There's also chance that the statement bonds[i] - totRead can be out of the atoms[] bounds, which could be the segfault.

最佳男配角 2024-09-12 08:59:32

听起来您正在使用 print 语句来调试分段错误:C 中的一大禁忌。

问题是 stdout 在大多数系统上都有缓冲,这意味着分段错误实际上发生的时间比您想象的要晚。使用 printf 无法可靠地确定程序何时出现段错误。

相反,您应该使用像 gdb 这样的调试器,它会告诉您导致分段错误的确切代码行。

如果您不知道如何使用 gdb,这里有一个我通过 Google 找到的快速教程:http://www.cs.cmu.edu/~gilpin/tutorial/

It sounds like you're using print statements to debug segmentation faults: a big no-no in C.

The problem is that stdout is buffered on most systems, which means that the segmentation fault is actually occurring later than you think. It is impossible to reliably determine out when your program is segfaulting using printf.

Instead, you should use a debugger like gdb, which will tell you the exact line of code that is causing the segmentation fault.

If you don't know how to use gdb, here's a quick tutorial I found by Google'ing: http://www.cs.cmu.edu/~gilpin/tutorial/

甜宝宝 2024-09-12 08:59:32

这很奇怪:

bonds = (int *) malloc(sizeof(int));
free(bonds);

atoms = (struct Atom *) malloc(sizeof(struct Atom));
free(atoms);

您分配内存,然后立即释放它,并使指针指向未分配的内存。

这行看起来也很危险:

atoms[bonds[i] - totRead].type[0] == 'H'

确保你的索引留在数组中。

This is odd:

bonds = (int *) malloc(sizeof(int));
free(bonds);

atoms = (struct Atom *) malloc(sizeof(struct Atom));
free(atoms);

You allocate memory and then you free it right afterwards and leaving your pointers pointing to unallocated memory.

This line looks also dangerous:

atoms[bonds[i] - totRead].type[0] == 'H'

Make sure you stay inside the array with your index.

离鸿 2024-09-12 08:59:32

编辑:去阅读这个 Accessing array value via指针算术与 C 中的下标 它应该帮助您理解什么是指针和数组

这些行实际上对代码的作用没有任何实际的净影响,因此您可以删除它们

bonds = (int *) malloc(sizeof(int));
free(bonds);

atoms = (struct Atom *) malloc(sizeof(struct Atom));
free(atoms);

这里的 malloc 行是无用的,并且会导致泄漏,因为您将氨基结构中的指针分配给完成后立即进行原子和键。

numAtoms = (*amino).numAtoms;

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
atoms = (*amino).atoms;

numBonds = atoms[nPos].numBonds;

bonds = (int *) malloc(sizeof(int) * numBonds);
bonds = atoms[nPos].bonds;

您应该暂时停止编码,并确保在执行其他操作之前了解指针,因为您显然不了解指针,并且在您了解之前这只会给您带来很多很多痛苦,但是这里是您的代码的一个版本,应该做一些更像你想要的事情:

int findHydrogen(struct Amino* amino, int nPos, float* diff, int totRead) {

    struct Atom* atoms;
    int* bonds;
    int numBonds;
    int i;
    int retVal;
    int numAtoms = amino->numAtoms;

    numAtoms = amino->numAtoms;
    atoms = amino->atoms;

    numBonds = atoms[nPos].numBonds;
    bonds = atoms[nPos].bonds;

    for(i = 0; i < amino->numAtoms; i++)
        printf("ATOM\t\t%d  %s\t0001\t%f\t%f\t%f\n", i + 1, atoms[i].type, atoms[i].x, atoms[i].y, atoms[i].z);

    for(i = 0; i < numBonds; i++) 
        if(atoms[bonds[i] - totRead].type[0] == 'H') {
            diff[0] = atoms[bonds[i] - totRead].x - atoms[nPos].x;
            diff[1] = atoms[bonds[i] - totRead].y - atoms[nPos].y;
            diff[2] = atoms[bonds[i] - totRead].z - atoms[nPos].z;

            retVal = bonds[i] - totRead;

            printf("2 %d\n", retVal);

            return retVal;
        }
}

EDIT: go read this Accessing array values via pointer arithmetic vs. subscripting in C it should help you understand what pointers and arrays are

These lines don't actually have any real net effect on what the code does so you can remove them

bonds = (int *) malloc(sizeof(int));
free(bonds);

atoms = (struct Atom *) malloc(sizeof(struct Atom));
free(atoms);

The malloc lines here are useless and result in a leak since you assign the pointer from the amino struct to atoms and bonds right after doing it.

numAtoms = (*amino).numAtoms;

atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
atoms = (*amino).atoms;

numBonds = atoms[nPos].numBonds;

bonds = (int *) malloc(sizeof(int) * numBonds);
bonds = atoms[nPos].bonds;

You should stop coding for a bit and make sure you understand pointers before you do much else because you clearly don't and it's just going to cause you lots and lots of pain until you do, however here is a version of your code that should do something more like what you want:

int findHydrogen(struct Amino* amino, int nPos, float* diff, int totRead) {

    struct Atom* atoms;
    int* bonds;
    int numBonds;
    int i;
    int retVal;
    int numAtoms = amino->numAtoms;

    numAtoms = amino->numAtoms;
    atoms = amino->atoms;

    numBonds = atoms[nPos].numBonds;
    bonds = atoms[nPos].bonds;

    for(i = 0; i < amino->numAtoms; i++)
        printf("ATOM\t\t%d  %s\t0001\t%f\t%f\t%f\n", i + 1, atoms[i].type, atoms[i].x, atoms[i].y, atoms[i].z);

    for(i = 0; i < numBonds; i++) 
        if(atoms[bonds[i] - totRead].type[0] == 'H') {
            diff[0] = atoms[bonds[i] - totRead].x - atoms[nPos].x;
            diff[1] = atoms[bonds[i] - totRead].y - atoms[nPos].y;
            diff[2] = atoms[bonds[i] - totRead].z - atoms[nPos].z;

            retVal = bonds[i] - totRead;

            printf("2 %d\n", retVal);

            return retVal;
        }
}
秋千易 2024-09-12 08:59:32

文件中是否有 #include ?我想知道您是否收到使用 printf() 隐式声明的 printf() 调用,因此可能使用了错误的调用约定。

您使用的编译器/平台是什么?您从构建中收到任何警告吗?

Do you have an #include <stdio.h> in the file? I wonder if you're getting a call to printf() that's using an implicit declaration of printf() and therefore might be using the wrong calling convention.

What's the compiler/platform you're using? Do you get any warnings from the build?

铃予 2024-09-12 08:59:32

你写的地方:

/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
/* Immediately lose track of the pointer to that space, once was stored
   in atoms, now being lost. */
atoms = (*amino).atoms;

我认为你的意图一定是这样的:

/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *)malloc(sizeof(struct Atom) * numAtoms);

/* Copy the input parameter into the newly-allocated memory. */
for (i = 0; i < numAtoms; i++)
    atoms[i] = (*amino).atoms[i];

也可以写成:

/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *)malloc(sizeof(struct Atom) * numAtoms);

/* Copy the input parameter into the newly-allocated memory. */
memcpy(atoms, (*amino).atoms, sizeof(struct Atom) * numAtoms);

在 C 中,没有内置的 equals (=) 运算符来复制数组,就像你想要的那样。相反,您所拥有的会丢失指向已分配内存的指针(以前存储在变量atoms中),然后继续开始循环的第一次迭代,其中atoms指向原子数组的“输入副本”。


Part of the problem is that you are calling free on memory, but then subsequently you continue to access the pointer to this freed memory. You must not access pointers to freed memory. To avoid this, replace all of your calls to free with:

#ifdef free
#    undef free
#endif
#define free(f) freeptr(&f)

void freeptr(void **f)
{
    /* This function intentionally segfaults if passed f==NULL, to alert
       the programmer that an error has been made.  Do not wrap this code
       with a check "if (f==NULL)", fix the problem where it is called. 

       To pass (*f==NULL) is a harmless 'no-op' as per the C standard
       free() function.

       If you must access the original, built-in free(), use (free)() to
       bypass the #define macro replacement of free().

     */

    (free)(*f);  /* free() must accept NULL happilly; this is safe. */
    *f = NULL;   /* Set the pointer to NULL, it cannot be used again. */
}

现在,您可以简单地将上述代码剪切并粘贴到程序顶部的某个位置。一个好的位置是在最终的#include 指令之后,但它必须出现在文件级范围内并且在代码中首次使用 free() 之前。

重新编译代码后,您会在 free(atom) 后立即发现总线错误和分段违规错误。这是正确的,freeptr() 的目的是导致您的代码立即崩溃,而不是导致您的代码滥用指针并导致难以调试的问题。

要最终更正您的内存分配,请务必转置以下行:

bonds = (int *) malloc(sizeof(int));
free(bonds);

其应为:

free(bonds);
bonds = (int *) malloc(sizeof(int));

您使用参数 diff 就好像传入至少包含三 (3) 个元素的数组一样。您应该验证调用者是否传递了足够的内存。


When allocating bonds, you must allocate memory for not one (1) integer, but as many integers as numBonds:

free(bonds);
bonds = (int *) malloc(sizeof(int) * numBonds);

或者,对于大多数 C 程序员来说更好:

free(bonds);
/* The calloc function performs the multiplication internally, and
   nicely zero-fills the allocated memory. */
bonds = calloc(numBonds, sizeof(int));

您需要更正原子的分配以分配正确的数量元素。目前,您还只分配大小为 sizeof(struct Atom) 的单个内存元素。此类元素的数组需要将一个元素的大小乘以元素的数量。

calloc() 函数很好,因为它为您分配一个数组,并将所有元素的内容初始化为零。 malloc() 不执行任何操作来初始化返回的内存,并且可能会导致程序中传播不可预测的值。如果您使用 malloc() 而不是 calloc(),则必须小心初始化数组元素。即使使用calloc(),您也必须初始化所有非零元素。


请注意,我从 malloc 的返回值中删除了强制转换。如果您正在编写 C 代码,则应该将其编译为 C 代码。除非您在 C++ 模式下进行编译,否则编译器不会抱怨缺少 void * 的强制转换。 C 源文件应以 .c 文件扩展名结尾,而不是 .cpp


正如 Walter Mundt 指出的那样,您意外地对已分配给指针 atoms 的输入参数之一的成员调用了 free()。您必须自行纠正此问题;上面的freeptr()不会为你突出显示这个错误。


其他人写道,您无法使用 printf() 来可靠地检测程序崩溃的位置。 printf() 的输出被缓冲并且其出现被延迟。

最好的选择是使用 gdb 来确定程序崩溃的确切行。如果您编译代码进行调试,则无需学习任何 gdb 命令即可执行此操作。

缺少的话,将: 替换

printf("Program ran to point A.\n");

为:

fprintf(stderr, "Program ran to point A.\nPress return.\n");
fflush(stderr); /* Force the output */
fflush(stdin);  /* Discard previously-typed keyboard input */
fgetc(stdin);   /* Await new input */
fflush(stdin);  /* Discard unprocessed input */

总的来说,我的建议是你暂时不要使用C 语言。如今计算机的速度如此之快,以至于我会质疑为什么您首先考虑使用 C。

别误会我的意思;我喜欢C语言。但 C 并不是万能的。 C 非常适合操作系统、嵌入式系统、高性能计算,以及其他成功的主要障碍是缺乏对计算机器的低级访问的情况。

就您而言,您似乎是一名科学家或工程师。我建议你学习并使用Python。 Python 可以提供易于阅读、易于验证的程序,您可以与其他化学家或工程师共享这些程序。 C 并不适合像 Python 那样快速编写健壮的代码。如果将来出现 Python 速度不够快无法满足您的目的的情况,您可以准备其他解决方案。

Where you have written:

/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
/* Immediately lose track of the pointer to that space, once was stored
   in atoms, now being lost. */
atoms = (*amino).atoms;

I think your intention must be this:

/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *)malloc(sizeof(struct Atom) * numAtoms);

/* Copy the input parameter into the newly-allocated memory. */
for (i = 0; i < numAtoms; i++)
    atoms[i] = (*amino).atoms[i];

which could also be written as:

/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *)malloc(sizeof(struct Atom) * numAtoms);

/* Copy the input parameter into the newly-allocated memory. */
memcpy(atoms, (*amino).atoms, sizeof(struct Atom) * numAtoms);

In C there is no built-in equals (=) operator to copy arrays as you seem to have intended. What you have instead loses track of the pointer to allocated memory, formerly stored in the variable atoms, and then proceeds to begin the first iteration of your loop with atoms pointing into the "input copy" of the atoms array.


Part of the problem is that you are calling free on memory, but then subsequently you continue to access the pointer to this freed memory. You must not access pointers to freed memory. To avoid this, replace all of your calls to free with:

#ifdef free
#    undef free
#endif
#define free(f) freeptr(&f)

void freeptr(void **f)
{
    /* This function intentionally segfaults if passed f==NULL, to alert
       the programmer that an error has been made.  Do not wrap this code
       with a check "if (f==NULL)", fix the problem where it is called. 

       To pass (*f==NULL) is a harmless 'no-op' as per the C standard
       free() function.

       If you must access the original, built-in free(), use (free)() to
       bypass the #define macro replacement of free().

     */

    (free)(*f);  /* free() must accept NULL happilly; this is safe. */
    *f = NULL;   /* Set the pointer to NULL, it cannot be used again. */
}

For now you can simply cut-and-paste the above code somewhere at the top of your program. A good place is after the ultimate #include directive, but it must occur at file-level scope and prior to your first use of free() in the code.

After recompiling your code, you will find Bus Errors and Segmentation Violation faults immediately after you free(atom). This is correct and the purpose of freeptr() is to lead your code to an immediate crash rather than the current situation where your code is misusing pointers and leading to problems which are very difficult for you to debug.

To finally correct your memory allocations, definitely transpose the lines:

bonds = (int *) malloc(sizeof(int));
free(bonds);

which should read:

free(bonds);
bonds = (int *) malloc(sizeof(int));

You use the argument diff as though you are passing in an array of at least three (3) elements. You should verify that the caller is passing enough memory.


When allocating bonds, you must allocate memory for not one (1) integer, but as many integers as numBonds:

free(bonds);
bonds = (int *) malloc(sizeof(int) * numBonds);

or, better for most C coders:

free(bonds);
/* The calloc function performs the multiplication internally, and
   nicely zero-fills the allocated memory. */
bonds = calloc(numBonds, sizeof(int));

You will need to correct the allocation of atoms to allocate a correct number of elements. Currently, you also are allocating only a single memory element of size sizeof(struct Atom). An array of such elements requires that you multiply the size of one element by the number of elements.

The calloc() function is nice because it allocates an array for you, and initializes the content of all elements to zero. malloc() does nothing to initialize the returned memory, and can result in unpredictable values propagating in your program. If you use malloc() rather than calloc(), you must take care to initialize the array elements. Even when using calloc(), you must initialize any non-zero elements.


Notice that I removed the cast from the return value of malloc. If you are writing C code, you should be compiling it as C code. The compiler will not complain about the lack of a cast from void * unless you are compiling in a C++ mode. C source files should end in .c file extensions, not .cpp.


As Walter Mundt pointed out, you are accidentally calling free() on a member of one of your input parameters, which you have assigned to the pointer atoms. You will have to correct this on your own; the above freeptr() will not highlight this mistake for you.


Others have written that you cannot use printf() to reliably detect where your program is crashing. The output from printf() is buffered and its appearance is delayed.

Your best bet is to use gdb to determine the exact line at which your program crashes. You won't have to learn any gdb commands to do this if you compile your code for debugging.

Lacking that, replace:

printf("Program ran to point A.\n");

with:

fprintf(stderr, "Program ran to point A.\nPress return.\n");
fflush(stderr); /* Force the output */
fflush(stdin);  /* Discard previously-typed keyboard input */
fgetc(stdin);   /* Await new input */
fflush(stdin);  /* Discard unprocessed input */

Overall, my suggestion is that you not use the C language for the time being. Computers are so fast these days that I would question why you have considered C in the first place.

Don't get me wrong; I love the C language. But C is not for everything. C is great for operating systems, embedded systems, high-performance computing, and for other cases where the main obstacle to success is lack of low-level access to the computing machinery.

In your case, you seem to be a scientist or engineer. I recommend you learn and use Python. Python lends itself to easily read, easily verified programs which you can share with your fellow chemists or engineers. C does not lend itself to quickly writing robust code as Python does. In that unlikely future event that Python is not fast enough for your purposes, there are other solutions which you will then be ready for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文