简体   繁体   English

释放C中的内存时出现分段错误

[英]Segmentation Fault while freeing memory in C

So I'm running the program to overcome integer overflow and while i'm debugging it runs through the first command hugePrint(p = parseString("12345")); 因此,我正在运行该程序来克服整数溢出,并且在调试时,它会通过第一个命令hugePrint(p = parseString(“ 12345”));运行; without an issue. 没有问题。 It runs the code after, hugeDestroyer(p); 它运行在greatDestroyer(p)之后的代码; and frees the memory without a problem. 并毫无问题地释放内存。 Once I run the next line of code in Ubuntu i'm getting a seg fault and it won't even print the numbers but on windows it prints "354913546879519843519843548943513179" and then gives me a seg fault after it runs hugeDestroyer(p); 一旦我在Ubuntu中运行下一行代码,我就会遇到段错误,它甚至不会打印数字,但是在Windows上它会显示“ 354913546879519843519843548943513179”,然后在运行hugeDestroyer(p)之后给我一段段错误; again. 再次。 Also Having problems running a NULL value through my parseString() function. 通过我的parseString()函数运行NULL值时也遇到问题。 Any help is greatly appreciated to shed light on the seg faults. 我们非常感谢您提供任何帮助,以帮助您找到有关分段故障的信息。

// 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

You have multiple problems in your code. 您的代码中有多个问题。

When you malloc to get a HugeInteger, you don't initialize the memory returned to 0. Since you have early return in your method when str == NULL , members of the struct aren't initialized so when you call hugeDestroyer on it, you get undefined behavior because you don't know what memory looks like in your struct. 当您使用malloc获取HugeInteger时,无需初始化返回0的内存。由于在str == NULL时您的方法已提前返回,因此未初始化该结构的成员,因此当您对它调用hugeDestroyer时,因为您不知道结构中的内存是什么样,所以得到未定义的行为。 More than likely p->digits is not null and it tries to free memory from it. 很有可能p-> digits不是null,它试图从中释放内存。


In hugeDestroyer you have this code 在hugeDestroyer中,您有以下代码

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

length is an int and is not dynamically allocated with malloc so calling free on this interprets the int as an address. length是一个int,不会使用malloc动态分配,因此,对此调用free会将int解释为地址。 Undefined behavior again. 再次出现未定义的行为。


Also in hugeDestroyer, you have this code 同样在hugeDestroyer中,您有此代码

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

This is also wrong, p->digits is allocated once with the right size. 这也是错误的, p->digits一次分配了正确的大小。 You only need to call free(p->digits) since c runtime remember the size of allocation. 您只需要调用free(p->digits)因为c运行时会记住分配的大小。 Your seg fault is again caused by free interpreting values in digits array as memory addresses to free. 您的段错误再次由将数字数组中的值免费解释为要释放的内存地址引起。

Assuming your huge integer representation is going to use decimal digits, ParseInt is going to need to break the argument down into individual decimal digits. 假设巨大的整数表示形式将使用十进制数字,则ParseInt将需要将参数分解为单个十进制数字。 Give this a try: 试试看:

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

I just looked at your HugeInteger struct and notice that length is not a pointer. 我只是看了看你的HugeInteger结构,注意到length不是指针。 Do not free it! 不要释放它!

As @EricFortin mentioned, you do not initialize your struct after calling malloc() : 正如@EricFortin所提到的,在调用malloc()之后,您无需初始化结构:

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

Same thing here: 同样的事情在这里:

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

Every time you return early from any of your ParseInt() or ParseString() functions, you have a memory leak because you do not free your HugeInteger pointer. 每次您从任何ParseInt()ParseString()函数中提前返回时,都会发生内存泄漏,因为您没有释放HugeInteger指针。

Do this (I was wrong the first time, another thanks to @EricFortin): 做到这一点(我第一次错了,再次感谢@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