使用stack或atoi时的运行时错误()

时间:2015-07-19 07:54:14

标签: c stack runtime-error

#define MAXL 256

第一遍:in = "25 7 * 14 - 6 +";运行顺利,答案正确。

第二次传递:in = "1 24 3 + * 41 -";程序在输出Num got in: 41后立即停止预期:继续循环然后进入减号然后pop(s)并减去41

我猜测我的程序耗尽了分配的空间,因为free()没有像我预期的那样完成他们的工作,但我不确定。

非常感谢任何帮助。谢谢!

double evaluatePost(char * in)
{
    double * op1 = NULL, * op2 = NULL, * msgr = NULL;
    int i, j;
    char * c = {0}, tempExp[MAXL] = {0}; 
    char ** token = NULL;
    Stack * s = createStack();

    strcpy(tempExp, in);        /* Copy in to a temporary array so strtok will not destroy in */

    for(c = strtok(tempExp, " "); c != NULL; ++i, c = strtok(NULL, " "))
    {
        if(isdigit(c[0]))
        {
            printf("\nNum got in: %s\n", c); /* Crash right after this line output 41 */
            system("PAUSE");
            msgr = (double*)malloc(sizeof(double)); /* I made a malloc check here, it never showed error */
            *msgr = atoi(c); /* I don't know if it crash at this line or the next one */
            push(s, msgr);  /* stack has no limit, receives stack* and void* */
            /* It never got pass to here after output 41 */
        }
        else
        {
            op2 = (double *)pop(s);
            op1 = (double *)pop(s);
            printf("\n%f %f %s\n", *op1, *op2, c);
            system("PAUSE");
            msgr = (double*)malloc(sizeof(double));
            if(!msgr)
            {
                printf("Memory allocation failed.\n");
                system("PAUSE");
                exit(1);
            }
            switch(*c)
            {
                case '+': *msgr = (*op1 + *op2); break;
                case '-': *msgr = (*op1 - *op2); break;
                case '*': *msgr = (*op1 * *op2); break;
                case '/': *msgr = (*op1 / *op2); break;
            }
            printf("\n%.1f\n", *msgr);
            system("PAUSE");
            /* Free the memory before they become orphans */            
            free(op1), free(op2);
            push(s, msgr);
        }       
    }   
    returnVal = *((double *)pop(s));
    makeEmpty(s);

    return returnVal;
}
void push(Stack * stack, void * dataInPtr)
{
    /* Define a new StackNode */
    StackNode * newPtr;

    /* Get some Memory */
    newPtr = (StackNode*)malloc(sizeof(StackNode));
    if(!newPtr)
    {
        printf("Out of memory");
        system("PAUSE");
        exit(1);
    }   
    /* Assign dataIn to dataPtr */
    newPtr->dataPtr = dataInPtr;

    /* Make the links */
    newPtr->link = stack->top;  /* Point both to top */
    stack->top = newPtr;        /* newPtr at top pointed to be head */
    (stack->count)++;
}
void * pop(Stack * stack)
{
    /* Hold the data */
    void * dataOutPtr;
    StackNode * temp;

    /* Check if stack is empty */
    if(stack->count == 0)
        dataOutPtr = NULL;
    else
    {
        /* Get the data and remove the node */
        temp = stack->top;                  /* temp points to top */
        dataOutPtr = stack->top->dataPtr;   /* dataOutPtr has data */
        stack->top = stack->top->link;      /* stack moves to next node */
        temp->link = NULL;                  /* break top node off stack */
        free(temp);                         /* frees memory */
        (stack->count)--;                   
    }
    return dataOutPtr;
}
typedef struct node
{
    void * dataPtr;
    struct Node * link;
} StackNode;

typedef struct
{
    int count;
    StackNode * top;
} Stack;

2 个答案:

答案 0 :(得分:0)

你的问题可能在于:

您正在释放pop()

中的堆栈节点
temp = stack->top;                  /* temp points to top */
dataOutPtr = stack->top->dataPtr;   /* dataOutPtr has data */
stack->top = stack->top->link;      /* stack moves to next node */
temp->link = NULL;                  /* break top node off stack */
free(temp);                         /* frees memory */

之后,您将evaluatePost()中的节点中的数据指针释放:

free(op1), free(op2);

内存的free序列应始终与malloc的顺序相反,即您应先分配Node,然后分配节点数据,并free free节点首先是数据,然后是Node本身。

您在使用某些输入时遇到问题而没有其他输入,因为这是未定义的行为

要了解有关C中未定义行为的更多信息,您可以在SO中搜索相关问题。

答案 1 :(得分:0)

您可以轻松添加遍历堆栈中所有节点的功能,而无需释放它们。如果您需要使用集合pushing所有节点并且不希望popfree数据,或者您需要更新节点,这会派上用场以popping之前的某种方式。您需要做的就是向堆栈添加一个tail指针,该指针将第一个节点pushed的地址保存到堆栈中。 e.g:

typedef struct
{
    int count;
    StackNode *top;
    StackNode *tail;
} Stack;

为什么呢?由于您有StackNode->link,因此无论如何,您的数据实际上都是linked-list形式。将指向第一个节点tail的{​​{1}}指针添加到堆栈中,只需简单地了解何时停止迭代pushed。通过一些小的调整,您可以执行您尝试的操作 - 迭代堆栈中的所有节点,而无需执行nodes / pop节点。

这是一个简短的例子,显示了所需的小调整。另请注意,清除会删除free 的所有强制转换(不要这样做),并在malloc调用自己的几次清理:

malloc

示例/输出

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

typedef struct node
{
    void *dataPtr;
    struct node *link;
} StackNode;

typedef struct
{
    int count;
    StackNode *top;
    StackNode *tail;
} Stack;

Stack *stackcreate ()
{
    Stack *s = malloc (sizeof *s);
    if (!s) {
        fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
        exit (EXIT_FAILURE);
    }
    s->count = 0;
    s->top = s->tail = NULL;

    return s;
}

void push(Stack * stack, void * dataInPtr)
{
    if (!stack) return;

    /* Define a new StackNode & allocate */
    StackNode *newPtr = malloc (sizeof *newPtr);
    if(!newPtr)
    {
        fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
        exit (EXIT_FAILURE);
    }   

    /* Assign dataIn to dataPtr */
    newPtr->dataPtr = dataInPtr;
    newPtr->link = stack->top;  /* Point both to top */

    /* Make the links */
    if (!stack->top)
        stack->tail = newPtr;
    stack->top = newPtr;        /* newPtr at top pointed to be head */
    (stack->count)++;
}

void * pop(Stack * stack)
{
    /* Hold the data */
    void * dataOutPtr;
    StackNode * temp;

    /* Check if stack is empty */
    if(stack->count == 0)
        dataOutPtr = NULL;
    else
    {
        /* Get the data and remove the node */
        temp = stack->top;                  /* temp points to top */
        dataOutPtr = stack->top->dataPtr;   /* dataOutPtr has data */
        stack->top = stack->top->link;      /* stack moves to next node */
        temp->link = NULL;                  /* break top node off stack */
        free(temp);                         /* frees memory */
        (stack->count)--;
        if (!stack->top) stack->tail = NULL;
    }
    return dataOutPtr;
}

int main (void) {

    char *lines[] = { "my cat has more...",
                    "has lots of fleas, ",
                    "my dog, the lab, " };
    size_t i = 0;
    size_t entries = sizeof lines/sizeof *lines;
    Stack *stack = stackcreate ();

    for (i = 0; i < entries; i++)
        push (stack, (void *)lines[i]);

    printf (" \niterating over nodes in stack without popping\n\n");
    StackNode *p; 
    for (p = stack->top; ;p = p->link) {
        printf (" %s\n", (char *)p->dataPtr);
        if (p == stack->tail)
            break;
    }

    printf ("\n popping items from stack\n\n");
    while (stack->top) {
        printf (" %s\n", (char *)pop (stack));
    }
    printf ("\n");

    return 0;
}