簡體   English   中英

釋放C中的內存時出現分段錯誤

[英]Segmentation Fault while freeing memory in C

因此,我正在運行該程序來克服整數溢出,並且在調試時,它會通過第一個命令hugePrint(p = parseString(“ 12345”));運行; 沒有問題。 它運行在greatDestroyer(p)之后的代碼; 並毫無問題地釋放內存。 一旦我在Ubuntu中運行下一行代碼,我就會遇到段錯誤,它甚至不會打印數字,但是在Windows上它會顯示“ 354913546879519843519843548943513179”,然后在運行hugeDestroyer(p)之后給我一段段錯誤; 再次。 通過我的parseString()函數運行NULL值時也遇到問題。 我們非常感謝您提供任何幫助,以幫助您找到有關分段故障的信息。

// main
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "Fibonacci.h"

// print a HugeInteger (followed by a newline character)
void hugePrint(HugeInteger *p)
{
    int i;

    if (p == NULL || p->digits == NULL)
    {
        printf("(null pointer)\n");
        return;
    }

    for (i = p->length - 1; i >= 0; i--)
        printf("%d", p->digits[i]);
    printf("\n");
}

int main(void)
{
    HugeInteger *p;

    hugePrint(p = parseString("12345"));
    hugeDestroyer(p);

    hugePrint(p = parseString("354913546879519843519843548943513179"));
    hugeDestroyer(p);

    hugePrint(p = parseString(NULL));
    hugeDestroyer(p);

    hugePrint(p = parseInt(246810));
    hugeDestroyer(p);

    hugePrint(p = parseInt(0));
    hugeDestroyer(p);

    hugePrint(p = parseInt(INT_MAX));
    hugeDestroyer(p);

    hugePrint(p = parseInt(UINT_MAX));
    hugeDestroyer(p);

    return 0;
}

//fibonacci.c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "Fibonacci.h"


// Functional Prototypes
/*
HugeInteger *hugeAdd(HugeInteger *p, HugeInteger *q)
{

}
*/


HugeInteger *hugeDestroyer(HugeInteger *p)
{
    int i;
    if ( p == NULL )
        return NULL;

    if( p->length != NULL)
        free(p->length);

    if ( p->digits != NULL )
    {
        for ( i = 0; i < p->length; i++)
            free( p->digits[i] );
        free( p->digits );
    }
    free( p );

    return NULL;

}

HugeInteger *parseString(char *str)
{

    int counter, reverseCount = 0;
    HugeInteger *numArray = malloc(sizeof(HugeInteger));

    if ( str == NULL)
    {
        return NULL;
    }
//checks for NULL pointer
    if ( numArray == NULL)
    {
        return NULL;
    }

// Dynamically allocate memory for array of numbers
    numArray->length = strlen(str);
    numArray->digits = malloc( sizeof(int) * numArray->length+1);

    if ( numArray->digits == NULL)
        return NULL;

    for( counter = numArray->length - 1 ; counter >= 0 ; counter--)
    {
        numArray->digits[reverseCount] = str[counter];

// Handles conversion from ASCII to integer format
        switch(numArray->digits[reverseCount])
        {
        case 48:
            numArray->digits[reverseCount] = 0;
            break;
        case 49:
            numArray->digits[reverseCount] = 1;
            break;
        case 50:
            numArray->digits[reverseCount] = 2;
            break;
        case 51:
            numArray->digits[reverseCount] = 3;
            break;
        case 52:
            numArray->digits[reverseCount] = 4;
            break;
        case 53:
            numArray->digits[reverseCount] = 5;
            break;
        case 54:
            numArray->digits[reverseCount] = 6;
            break;
        case 55:
            numArray->digits[reverseCount] = 7;
            break;
        case 56:
            numArray->digits[reverseCount] = 8;
            break;
        case 57:
            numArray->digits[reverseCount] = 9;
            break;
        default:
            numArray->digits[reverseCount] = 0;
            break;
        }
        reverseCount++;
    }

    return numArray;

}

HugeInteger *parseInt(unsigned int n)
{
    HugeInteger *number = malloc(sizeof(HugeInteger));
    if( number == NULL )
        return NULL;

    if(n > UINT_MAX )
        return NULL;

    number = n;

    return number;

}
unsigned int *toUnsignedInt(HugeInteger *p)
{
    unsigned int *newInteger = malloc(sizeof(unsigned int));

    if( newInteger == NULL)
    {
        return NULL;
    }

    if (p == NULL || p > UINT_MAX )
    {
        return NULL;
    }

    newInteger = p;

    return newInteger;

}
/*
HugeInteger *fib(int n)
{
    // base cases: F(0) = 0, F(1) = 1
    if (n < 2)
        return n;
// definition of Fibonacci: F(n) = F(n – 1) + F(n - 2)
    return fib(n – 1) + fib(n – 2);
}
*/

//fibonacci.h
#ifndef __FIBONACCI_H
#define __FIBONACCI_H

typedef struct HugeInteger
{
    // a dynamically allocated array to hold the digits of a huge integer
    int *digits;

    // the number of digits in the huge integer (approx. equal to array length)
    int length;
} HugeInteger;


// Functional Prototypes

HugeInteger *hugeAdd(HugeInteger *p, HugeInteger *q);

HugeInteger *hugeDestroyer(HugeInteger *p);

HugeInteger *parseString(char *str);

HugeInteger *parseInt(unsigned int n);

unsigned int *toUnsignedInt(HugeInteger *p);

HugeInteger *fib(int n);


#endif

您的代碼中有多個問題。

當您使用malloc獲取HugeInteger時,無需初始化返回0的內存。由於在str == NULL時您的方法已提前返回,因此未初始化該結構的成員,因此當您對它調用hugeDestroyer時,因為您不知道結構中的內存是什么樣,所以得到未定義的行為。 很有可能p-> digits不是null,它試圖從中釋放內存。


在hugeDestroyer中,您有以下代碼

if( p->length != NULL)
    free(p->length);

length是一個int,不會使用malloc動態分配,因此,對此調用free會將int解釋為地址。 再次出現未定義的行為。


同樣在hugeDestroyer中,您有此代碼

for ( i = 0; i < p->length; i++)
    free( p->digits[i] );
free( p->digits );

這也是錯誤的, p->digits一次分配了正確的大小。 您只需要調用free(p->digits)因為c運行時會記住分配的大小。 您的段錯誤再次由將數字數組中的值免費解釋為要釋放的內存地址引起。

假設巨大的整數表示形式將使用十進制數字,則ParseInt將需要將參數分解為單個十進制數字。 試試看:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "Fibonacci.h"

void hugeDestroyer(HugeInteger *p)
{
    if ( p != NULL ) {
        free( p->digits );
        free( p );
    }
}

HugeInteger *parseString(char *str)
{
    HugeInteger *huge;
    int i;

    if (str == NULL)
        goto error1;

    if ((huge = malloc(sizeof *huge)) == NULL)
        goto error1;

    huge->length = strlen(str);

    if ((huge->digits = malloc(huge->length * sizeof *huge->digits)) == NULL)
        goto error2;

    for (i = 0; i < huge->length; i++) {
        huge->digits[huge->length-i-1] =
            (str[i] >= '0' && str[i] <= '9') ? str[i] - '0' : 0;
    }

    return huge;

//error3:
//    free(huge->digits);
error2:
    free(huge);
error1:
    return NULL;
}

HugeInteger *parseInt(unsigned int n)
{
    HugeInteger *huge;
    int digits[10]; // largest 32-bit unsigned integer has 10 digits in base 10
    int length;

    if ((huge = malloc(sizeof *huge)) == NULL)
        goto error1;

    length = 0;
    do {
        digits[length++] = n % 10;
        n /= 10;
    }
    while (n);

    huge->length = length;

    if ((huge->digits = malloc(huge->length * sizeof *huge->digits)) == NULL)
        goto error2;

    memcpy(huge->digits, digits, huge->length * sizeof *huge->digits);

    return huge;

//error3:
//    free(huge->digits);
error2:
    free(huge);
error1:
    return NULL;
}

我只是看了看你的HugeInteger結構,注意到length不是指針。 不要釋放它!

正如@EricFortin所提到的,在調用malloc()之后,您無需初始化結構:

HugeInteger *numArray = malloc(sizeof(HugeInteger));
numArray->length = 0 ; // add me
numArray->digits = NULL ; // add me

同樣的事情在這里:

HugeInteger *number = malloc(sizeof(HugeInteger));
numArray->length = 0 ; // add me
numArray->digits = NULL ; // add me

每次您從任何ParseInt()ParseString()函數中提前返回時,都會發生內存泄漏,因為您沒有釋放HugeInteger指針。

做到這一點(我第一次錯了,再次感謝@EricFortin):

    for ( i = 0; i < p->length; i++) // remove me
        free( p->digits[i] ); // remove me
    free( p->digits ); // keep me

暫無
暫無

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

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