简体   繁体   English

指针和动态记忆

[英]Pointers and Dynamic Memory

I have a function that returns a pointer to an array. 我有一个函数,它返回一个指向数组的指针。 I'm running it in a loop and free() seems to be giving me problems. 我正在循环中运行它而free()似乎给了我一些问题。 I'm not sure where, but it appears that somewhere in the main loop the memory that I'm trying to free is being used. 我不知道在哪里,但似乎在主循环的某个地方我正在尝试释放的内存被使用。 I'm using Xcode 3.2.1 in 10.6 | 我在10.6中使用Xcode 3.2.1 | Debug | 调试| x86_64 build. x86_64 build。

The program will run through the main loop one time; 该程序将在主循环中运行一次; the second time it encounters the free() it gives me the following error: 第二次遇到free()时会出现以下错误:

malloc: *** error for object 0x100100180: incorrect checksum for freed object -
object was probably modified after being freed.

Can someone point out (no pun intended) what I'm doing wrong with pointers here? 有人可以指出(没有双关语)我在这里用指针做错了吗?

Here is the program: 这是程序:

int main(int argc, char **argv) {
    int *partition;
    int lowerLimit;
    int upperLimit;

    // snip ... got lowerLimit and upperLimit from console arguments

    // this is the 'main loop':
    for (int i = lowerLimit; i <= upperLimit; i += 2) {
        partition = goldbachPartition(i);
        printOutput(partition[0], partition[1], i);
        free(partition); // I get problems on the second iteration here
    }

    return 0;
}


int *goldbachPartition(int x) {
    int solved = 0;
    int y, z;
    int *primes;
    int *result;

    result = intAlloc(2);

    primes = atkinsPrimes(x);

    for (int i = intCount(primes)-1; i >= 0; i--) {
        y = primes[i];
        for (int j = 0; j < y; j++) {
            z = primes[j];
            if (z + y >= x) {
                break;
            }
        }
        if (z + y == x) {
            solved = 1;
            result[0] = y;
            result[1] = z;
            break;
        } else if (y == z) {
            result[0] = 0;
            result[1] = 0;
            break;
        }
    }
    free(primes);

    return result;
}


int *atkinsPrimes(int limit) {
    int *primes;
    int *initialPrimes;
    int *filtered;
    int *results;
    int counter = 0;
    int sqrtLimit;
    int xLimit;
    int resultsSize;

    primes = intAlloc(limit+1);
    intFillArray(primes, limit+1, 0);

    sqrtLimit = floor(sqrt(limit));
    xLimit = floor(sqrt((limit+1) / 2));

    // these loops are part of the Atkins Sieve implementation
    for (int x = 1; x < xLimit; x++) {
        int xx = x*x;
        for (int y = 1; y < sqrtLimit; y++) {
            int yy = y*y;
            int n = 3*xx + yy;
            if (n <= limit && n % 12 == 7) {
                primes[n] = (primes[n] == 1) ? 0 : 1;
            }
            n += xx;
            if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
                primes[n] = (primes[n] == 1) ? 0 : 1;
            }
            if (x > y) {
                n -= xx + 2*yy;
                if (n <= limit && n % 12 == 11) {
                    primes[n] = (primes[n] == 1) ? 0 : 1;
                }
            }
        }
    }

    for (int n = 5; n < limit; n++) {
        if (primes[n] == 1) {
            for (int k = n*n; k < limit; k += n*n) {
                primes[k] = 0;
            }
        }
    }

    initialPrimes = intAlloc(2);

    if (limit >= 2) {
        initialPrimes[counter++] = 2;
    }
    if (limit >= 3) {
        initialPrimes[counter++] = 3;
    }

    filtered = intFilterArrayKeys(primes, limit+1);
    results = intMergeArrays(initialPrimes, filtered, counter, trueCount(primes, limit+1));
    resultsSize = counter + trueCount(primes, limit+1);

    free(primes);
    free(initialPrimes);
    free(filtered);

    results[resultsSize] = 0;

    return results;
}

int trueCount(int *subject, int arraySize) {
    int count = 0;

    for (int i = 0; i < arraySize; i++) {
        if (subject[i] == 1) {
            count++;
        }
    }
    return count;
}


int intCount(int *subject) {
    // warning: expects 0 terminated array.
    int count = 0;

    while (*subject++ != 0) {
        count++;
    }

    return count;
}


void intFillArray(int *subject, int arraySize, int value) {
    for (int i = 0; i < arraySize; i++) {
        subject[i] = value;
    }
}


int *intFilterArrayKeys(int *subject, int arraySize) {
    int *filtered;
    int count = 0;

    filtered = intAlloc(trueCount(subject, arraySize));
    for (int i = 0; i < arraySize; i++) {
        if (subject[i] == 1) {
            filtered[count++] = i;
        }
    }

    return filtered;
}


int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2) {
    int *merge;
    int count = 0;

    merge = intAlloc(arraySize1 + arraySize2);

    for (int i = 0; i < arraySize1; i++) {
        merge[count++] = subject1[i];
    }
    for (int i = 0; i < arraySize2; i++) {
        merge[count++] = subject2[i];
    }

    return merge;
}

int *intAlloc(int amount) {
    int *ptr;
    ptr = (int *)malloc(amount * sizeof(int));
    if (ptr == NULL) {
        printf("Error: NULL pointer\n");
    }
    return ptr;
}

void printOutput(int num1, int num2, int rep) {
    if (num1 == 0) {
        printf("%d: No solution\n", rep);
        exit(0);
    } else {
        printf("%d = %d + %d\n", rep, num1, num2);
    }
}

Why is intAlloc not returning int* ? 为什么intAlloc不返回int *

int *intAlloc(int amount) {
    int *ptr;

    ptr = (int *)malloc(amount * sizeof(int));
    if(ptr == NULL) {
        printf("Error: NULL pointer\n");
        exit(1);
    }
    return ptr; //like this
}

EDIT (after your update): 编辑 (更新后):

On atkinsPrimes() where is filtered being intAlloc()ed ? atkinsPrimes()中过滤的是intAlloc()ed

int *atkinsPrimes(int limit) {
    int *primes;
    int *initialPrimes;
    int *filtered;
    int *results;
    int resultsSize;

    primes = intAlloc(limit+1);

    // ...

    initialPrimes = intAlloc(2);

    // ...

    resultsSize = counter + trueCount(primes, limit+1);

    free(primes);
    free(initialPrimes);
    free(filtered); // Where was it intAlloc()ed?

    results[resultsSize] = 0; // make the array 0-terminated to make it easier to work with

    return results;
}

EDIT (after your N-th update): 编辑 (在第N次更新后):

This is a compilable version of your code. 这是您的代码的可编译版本。 It ran smooth on my machine, no crashes. 它在我的机器上顺利运行,没有崩溃。 Compiled with g++ (due to declarations of variables inside the for statement): 用g ++编译(由于for语句中的变量声明):

g++ (Debian 4.3.2-1.1) 4.3.2 g ++(Debian 4.3.2-1.1)4.3.2

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int *goldbachPartition(int x);
int *atkinsPrimes(int limit);
int trueCount(int *subject, int arraySize);
int intCount(int *subject) ;
void intFillArray(int *subject, int arraySize, int value);
int *intFilterArrayKeys(int *subject, int arraySize);
int *intAlloc(int amount);
void printOutput(int num1, int num2, int rep) ;
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2);


int main(int argc, char **argv) {
    if (argc < 3) {
        printf("Usage: ./program <lower> <upper>\n");
        return 0;
    }


    int *partition;
    int lowerLimit = atoi(argv[1]);
    int upperLimit = atoi(argv[2]);

    // snip ... got lowerLimit and upperLimit from console arguments

    // this is the 'main loop':
    for (int i = lowerLimit; i <= upperLimit; i += 2) {
        partition = goldbachPartition(i);
        printOutput(partition[0], partition[1], i);
        free(partition); // I get problems on the second iteration here
    }

    return 0;
}


int *goldbachPartition(int x) {
    int solved = 0;
    int y, z;
    int *primes;
    int *result;

    result = intAlloc(2);

    primes = atkinsPrimes(x);

    for (int i = intCount(primes)-1; i >= 0; i--) {
        y = primes[i];
        for (int j = 0; j < y; j++) {
            z = primes[j];
            if (z + y >= x) {
                break;
            }
        }
        if (z + y == x) {
            solved = 1;
            result[0] = y;
            result[1] = z;
            break;
        } else if (y == z) {
            result[0] = 0;
            result[1] = 0;
            break;
        }
    }
    free(primes);

    return result;
}


int *atkinsPrimes(int limit) {
    int *primes;
    int *initialPrimes;
    int *filtered;
    int *results;
    int counter = 0;
    int sqrtLimit;
    int xLimit;
    int resultsSize;

    primes = intAlloc(limit+1);
    intFillArray(primes, limit+1, 0);

    sqrtLimit = floor(sqrt(limit));
    xLimit = floor(sqrt((limit+1) / 2));

    for (int x = 1; x < xLimit; x++) {
        int xx = x*x;
        for (int y = 1; y < sqrtLimit; y++) {
            int yy = y*y;
            int n = 3*xx + yy;
            if (n <= limit && n % 12 == 7) {
                primes[n] = (primes[n] == 1) ? 0 : 1;
            }
            n += xx;
            if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
                primes[n] = (primes[n] == 1) ? 0 : 1;
            }
            if (x > y) {
                n -= xx + 2*yy;
                if (n <= limit && n % 12 == 11) {
                    primes[n] = (primes[n] == 1) ? 0 : 1;
                }
            }
        }
    }

    for (int n = 5; n < limit; n++) {
        if (primes[n] == 1) {
            for (int k = n*n; k < limit; k += n*n) {
                primes[k] = 0;
            }
        }
    }

    initialPrimes = intAlloc(2);

    if (limit >= 2) {
        initialPrimes[counter++] = 2;
    }
    if (limit >= 3) {
        initialPrimes[counter++] = 3;
    }

    filtered = intFilterArrayKeys(primes, limit+1);
    results = intMergeArrays(initialPrimes, filtered, counter, trueCount(primes, limit+1));
    resultsSize = counter + trueCount(primes, limit+1);

    free(primes);
    free(initialPrimes);
    free(filtered);

    results[resultsSize] = 0;

    return results;
}

int trueCount(int *subject, int arraySize) {
    int count = 0;

    for (int i = 0; i < arraySize; i++) {
        if (subject[i] == 1) {
            count++;
        }
    }
    return count;
}


int intCount(int *subject) {
    // warning: expects 0 terminated array.
    int count = 0;

    while (*subject++ != 0) {
        count++;
    }

    return count;
}


void intFillArray(int *subject, int arraySize, int value) {
    for (int i = 0; i < arraySize; i++) {
        subject[i] = value;
    }
}


int *intFilterArrayKeys(int *subject, int arraySize) {
    int *filtered;
    int count = 0;

    filtered = intAlloc(trueCount(subject, arraySize));
    for (int i = 0; i < arraySize; i++) {
        if (subject[i] == 1) {
            filtered[count++] = i;
        }
    }

    return filtered;
}


int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2) {
    int *merge;
    int count = 0;

    merge = intAlloc(arraySize1 + arraySize2);

    for (int i = 0; i < arraySize1; i++) {
        merge[count++] = subject1[i];
    }
    for (int i = 0; i < arraySize2; i++) {
        merge[count++] = subject2[i];
    }

    return merge;
}

int *intAlloc(int amount) {
    int *ptr;
    ptr = (int *)malloc(amount * sizeof(int));
    if (ptr == NULL) {
        printf("Error: NULL pointer\n");
    }
    return ptr;
}

void printOutput(int num1, int num2, int rep) {
    if (num1 == 0) {
        printf("%d: No solution\n", rep);
        exit(0);
    } else {
        printf("%d = %d + %d\n", rep, num1, num2);
    }
}

Since you are still omitting some source, I can only imagine that the problem is hidden there. 由于您仍在省略某些来源,因此我只能想象问题隐藏在那里。

EDIT : (my last update) 编辑 :(我上次更新)

To assist your debugging, you should replace your main() function by the one below: 为了帮助您进行调试,您应该用以下方法替换main()函数:

int main(int argc, char **argv) 
{
    int *primes = NULL;

    primes = atkinsPrimes(44); // Evil magic number

    free(primes);

    return 0;
}

Having a minimal example to reproduce the behavior you pointed out is much better then the whole thing. 有一个最小的例子来重现你指出的行为比整个事情要好得多。 Have fun with atkinsPrimes(44) 玩得开心atkinsPrimes(44)

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

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