私はクラスのためにこのプログラムを書いています。このプログラムは、スタックを使用した単純な括弧チェッカー アプリケーションです。この場合、静的配列を使用してスタック データ構造を実装しました。プログラムは正常にビルドされますが、このランタイム エラーが発生し、これまでのところ問題の原因を特定できませんでした。
malloc を使用して割り当てられていないメモリを解放しようとしたことが問題の原因である可能性があることを私が理解している情報はほとんどありません。しかし、次のコードでは、これがどこで発生しているのかわかりません。
以下は、静的配列を使用したスタックのインターフェース実装コードです。また、スタックに文字を追加するためのスタック インターフェイス コードと、ルーチンをテストするためのドライバー プログラムも追加しました。
#include "stack.h"
#include "stdlib.h" /* malloc, free */
#include "stdio.h"
#define MAXSTACKSIZE 10
struct stack_record {
generic_ptr base[MAXSTACKSIZE];
generic_ptr * top;
};
unsigned int num_elements(stack * const p_S)
{
unsigned int numels = ((*p_S)->top - (*p_S)->base);
/* return ((*p_S)->top - (*p_S)->base); */
printf("number of elements in the stack is: %u\n", numels);
return numels;
}
status init_stack(stack * const p_S)
{
stack_record * record = (stack_record *)malloc(sizeof(stack_record));
if(record == NULL) {
return ERROR;
}
record->top = record->base;
*p_S = record;
return OK;
}
bool empty_stack(stack * const p_S)
{
if(num_elements(p_S) == 0)
{
printf("stack is EMPTY!\n");
return TRUE;
}
else
{
printf("stack NOT Empty!\n");
return FALSE;
}
}
status push(stack * const p_S, generic_ptr const data)
{
if (num_elements(p_S) == MAXSTACKSIZE)
return ERROR;
*( (*p_S)->top ) = data;
(*p_S)->top++;
return OK;
}
status pop(stack * const p_S, generic_ptr * const p_data)
{
if (empty_stack(p_S) == TRUE)
return ERROR;
*p_data = *((*p_S)->top);
(*p_S)->top--;
/* ((*p_S)->top)--; */
return OK;
}
status top(stack *const p_S, generic_ptr * const p_data)
{
if (pop(p_S, p_data) == ERROR)
return ERROR;
return push(p_S, *p_data);
}
void destroy_stack(stack * const p_S, void (* const p_func_f)())
{
if ((p_func_f) != NULL) {
generic_ptr * curr;
for(curr = (*p_S)->top;
curr != (*p_S)->base;
++curr)
(*p_func_f)(*curr);
}
free(*p_S); /*free the dynamically allocated memory on the heap */
*p_S = NULL;
}
以下は、文字用のスタック インターフェイス ルーチンです。
/*************************************************************************/
/* adapted from Esakov and Weiss, Section 5.2 */
/*************************************************************************/
#include "char_stack.h"
#include "stdlib.h" /* malloc */
#include "stdio.h"
#define DEBUG 1
status push_char(stack * const p_S, char const c)
{
/*
* Push the character c onto the stack.
*/
char * p_c = (char *) malloc(sizeof(char));
if(p_c == NULL)
return ERROR;
*p_c = c;
if(DEBUG)
/* Debug code: begin */
{
printf("Character to PUSH on the stack: %c\n", *p_c);
}
/* Debug code: end */
if (push(p_S, (generic_ptr)p_c) == ERROR) {
if(DEBUG)
printf("char_stack: push_char: failed to push the character on the stack!\n");
free(p_c);
return ERROR;
}
return OK;
}
status pop_char(stack * const p_S, char * const p_c)
{
/*
* Pop the stack. Return the character in p_c.
*/
generic_ptr p_data;
if( pop(p_S, &p_data) == ERROR)
return ERROR;
*p_c = *((char*)p_data);
if(DEBUG)
/*Debug code: begin */
printf("char_stack.c::pop_char: Character to POP on the stack: %c\n", *p_c);
/*Debug code: end */
free(p_data);
return OK;
}
status top_char(stack * const p_S, char * const p_c)
{
/*
* Return the top character from the stack in p_c
*/
generic_ptr p_data;
if (top(p_S, &p_data) == ERROR)
return ERROR;
*p_c = *((char *)p_data);
return OK;
}
アプリケーションのドライバー プログラム:
/**************************************************************************/
/* adapted from Esakov and Weiss, Section 5.2 */
/**************************************************************************/
#include "stdio.h"
#include "stdlib.h"
#include "char_stack.h"
char matching_symbol(char const c)
{
switch(c) {
case '(': return ')';
case ')': return '(';
case '}': return '{';
case '{': return '}';
case '[': return ']';
case ']': return '[';
}
return 0;
}
status consume_char(stack * const p_S, char input)
{
switch (input) {
case '(':
case '{':
case '[':
return push_char(p_S, input);
case ')':
case '}':
case ']':
{
char c;
if (pop_char(p_S, &c) == ERROR || c != matching_symbol(input)) {
return ERROR;
} else {
return OK;
}
}
default:
return OK;
}
}
int main(int argc, char * argv[])
{
if (argc == 1) {
exit(EXIT_SUCCESS);
}
{
stack S;
init_stack(&S);
{
char *ptr;
for (ptr = argv[1];
*ptr != '\0' && consume_char(&S, *ptr) == OK;
++ptr);
if (*ptr == '\0' && empty_stack(&S)) {
destroy_stack(&S,free);
exit(EXIT_SUCCESS);
} else {
destroy_stack(&S,free);
exit(EXIT_FAILURE);
}
}
}
exit(EXIT_SUCCESS);
}
ドライバープログラムに追加したいのですが、スタックを破棄する呼び出しがこの問題の原因であると絞り込みました。しかし、このコードを確認したところ、このコードは問題なく、問題は別の場所にあると考えています。
[編集 1]: 完全を期すために、これらの関数が呼び出されているドライバー コードを追加しました。[編集 2]: キャラクター用のスタック インターフェイス ルーチンを追加しました。