簡體   English   中英

指針和動態記憶

[英]Pointers and Dynamic Memory

我有一個函數,它返回一個指向數組的指針。 我正在循環中運行它而free()似乎給了我一些問題。 我不知道在哪里,但似乎在主循環的某個地方我正在嘗試釋放的內存被使用。 我在10.6中使用Xcode 3.2.1 | 調試| x86_64 build。

該程序將在主循環中運行一次; 第二次遇到free()時會出現以下錯誤:

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

有人可以指出(沒有雙關語)我在這里用指針做錯了嗎?

這是程序:

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

為什么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
}

編輯 (更新后):

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

編輯 (在第N次更新后):

這是您的代碼的可編譯版本。 它在我的機器上順利運行,沒有崩潰。 用g ++編譯(由於for語句中的變量聲明):

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

由於您仍在省略某些來源,因此我只能想象問題隱藏在那里。

編輯 :(我上次更新)

為了幫助您進行調試,您應該用以下方法替換main()函數:

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

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

    free(primes);

    return 0;
}

有一個最小的例子來重現你指出的行為比整個事情要好得多。 玩得開心atkinsPrimes(44)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM