在 Visual Studio 中检测到堆损坏,但程序在另一个 C 编译器中运行良好:为什么?
Heap Corruption Detected in Visual Studio, but program runs fine in another C compiler: why?
我尝试搜索这个问题,但找不到任何答案。我编写了一个程序,它使用链表实现堆栈及其操作。该程序在 C Web IDE 上编译和 运行 完美。
当我 运行 Visual Studio 中的程序时,它失败并给我以下错误:
调试错误!
程序:C:\Users...我的文件路径
检测到堆损坏:在 0x011058C8 处的正常块 (#78) 之后。
CRT 检测到应用程序在堆缓冲区结束后写入内存。
因为我的代码 运行 在其他地方都很好,这一定是我使用 Visual Studio 的方式的问题。有任何想法吗?我是 Visual Studio 的新手,恐怕这可能有些愚蠢,但我似乎无法弄明白。
我在下面包含了我的代码,请注意,失败是由 Visual Studio 中的 pop() 函数引起的。
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
struct Node* top = NULL; //initialize head
void push(int x);
void push(int x) {
struct Node* add = (struct Node*)malloc(sizeof(struct Node*));
add->data = x;
add->next = top; //make add point to what top (head) points to (old 1st)
top = add; //make top point to add (new 1st)
}
void pop();
void pop() {
if (top == NULL) return;
struct Node* temp = top;
top = top->next;
free(temp);
}
int topp();
int topp() {
return top->data;
}
int exist();
int exist() {
if (top->next) {
return 1;
}
else {
return 0;
}
}
void PrintIt();
void PrintIt() {
struct Node* temp = top;
while (temp!= NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
push(1); PrintIt();
push(44); PrintIt();
push(23); PrintIt();
pop(); PrintIt();
push(9); PrintIt();
return 0;
}
如果您正在做一些未定义的行为(动态内存分配是这些问题的真正温床),可能发生的未定义的事情之一是它会工作得很好。
这绝不表示您做的是正确的事情,UB 是应该避免的事情,因为它可能在另一个系统、另一个编译器甚至下周二 3:05 下午以不同方式运行: -)
我会提到几件事:
- 您不需要在定义之前立即声明所有这些函数(原型)。如果定义尚未声明,则它充当声明。
- 您的
exist()
函数很可能因空列表而崩溃,因为它取消引用 top
。如果你的目的是检测一个非空列表,你可以只使用 return (top != NULL);
.
- 你不应该在 C 中显式地转换
malloc
的 return 值,它会导致某些细微的错误。
而且,事实上,在查看最后一个要点时,您有一个错误(不是特别与转换有关,只是在该特定行上):
struct Node* add = (struct Node*)malloc(sizeof(struct Node*));
// ^
// oops!
struct Node*
的大小是指向您的结构的 指针 的大小,通常(但不一定)四个或八个八位字节。鉴于您的实际结构有一个整数 和 一个指针,该大小将不够大。
它可能适用于某些 提供最小动态内存分配的系统,但绝对不建议这样做。你应该这样做:
struct Node *add = malloc(sizeof(struct Node));
// ^^^^^^^^^^^
// size of the node, not pointer
该行已删除演员表,并且大小正确。
我尝试搜索这个问题,但找不到任何答案。我编写了一个程序,它使用链表实现堆栈及其操作。该程序在 C Web IDE 上编译和 运行 完美。
当我 运行 Visual Studio 中的程序时,它失败并给我以下错误:
调试错误! 程序:C:\Users...我的文件路径 检测到堆损坏:在 0x011058C8 处的正常块 (#78) 之后。 CRT 检测到应用程序在堆缓冲区结束后写入内存。
因为我的代码 运行 在其他地方都很好,这一定是我使用 Visual Studio 的方式的问题。有任何想法吗?我是 Visual Studio 的新手,恐怕这可能有些愚蠢,但我似乎无法弄明白。
我在下面包含了我的代码,请注意,失败是由 Visual Studio 中的 pop() 函数引起的。
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
struct Node* top = NULL; //initialize head
void push(int x);
void push(int x) {
struct Node* add = (struct Node*)malloc(sizeof(struct Node*));
add->data = x;
add->next = top; //make add point to what top (head) points to (old 1st)
top = add; //make top point to add (new 1st)
}
void pop();
void pop() {
if (top == NULL) return;
struct Node* temp = top;
top = top->next;
free(temp);
}
int topp();
int topp() {
return top->data;
}
int exist();
int exist() {
if (top->next) {
return 1;
}
else {
return 0;
}
}
void PrintIt();
void PrintIt() {
struct Node* temp = top;
while (temp!= NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
push(1); PrintIt();
push(44); PrintIt();
push(23); PrintIt();
pop(); PrintIt();
push(9); PrintIt();
return 0;
}
如果您正在做一些未定义的行为(动态内存分配是这些问题的真正温床),可能发生的未定义的事情之一是它会工作得很好。
这绝不表示您做的是正确的事情,UB 是应该避免的事情,因为它可能在另一个系统、另一个编译器甚至下周二 3:05 下午以不同方式运行: -)
我会提到几件事:
- 您不需要在定义之前立即声明所有这些函数(原型)。如果定义尚未声明,则它充当声明。
- 您的
exist()
函数很可能因空列表而崩溃,因为它取消引用top
。如果你的目的是检测一个非空列表,你可以只使用return (top != NULL);
. - 你不应该在 C 中显式地转换
malloc
的 return 值,它会导致某些细微的错误。
而且,事实上,在查看最后一个要点时,您有一个错误(不是特别与转换有关,只是在该特定行上):
struct Node* add = (struct Node*)malloc(sizeof(struct Node*));
// ^
// oops!
struct Node*
的大小是指向您的结构的 指针 的大小,通常(但不一定)四个或八个八位字节。鉴于您的实际结构有一个整数 和 一个指针,该大小将不够大。
它可能适用于某些 提供最小动态内存分配的系统,但绝对不建议这样做。你应该这样做:
struct Node *add = malloc(sizeof(struct Node));
// ^^^^^^^^^^^
// size of the node, not pointer
该行已删除演员表,并且大小正确。