【发布时间】:2015-08-27 03:59:51
【问题描述】:
我在 C 语言中玩弄指针,遇到了我不理解的行为。它涉及到在以下程序中使用static 关键字:
/**
* Simple LIFO stack implemented using linked lists
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct LinkedList LinkedList;
struct LinkedList{
int value;
LinkedList *next;
};
int pop(LinkedList **list){
LinkedList *next;
int ret;
ret = (*list)->value;
next = (*list)->next;
//free(*list);
*list = next;
return ret;
}
void push(LinkedList **list, int value){
LinkedList *new = (LinkedList*)malloc(sizeof(LinkedList));
new->value = value;
new->next = (*list);
*list = new;
}
int main() {
LinkedList *myList;
for(int i = 0; i<10; i++)
push(&myList, i);
while(myList!=NULL)
printf("popped %i\n", pop(&myList));
return 0;
}
当我编译并运行上面的代码时,我遇到了分段错误。但是,当我将 myList 的声明更改为 static LinkedList *myList 时,程序(看似)完美地工作:
output without static keyword:
popped 9
popped 8
popped 7
popped 6
popped 5
popped 4
popped 3
popped 2
popped 1
popped 0
popped 1
popped 1970220846
Segmentation fault (core dumped)
output with static keyword:
popped 9
popped 8
popped 7
popped 6
popped 5
popped 4
popped 3
popped 2
popped 1
popped 0
我真的不明白为什么会这样。我认为它与范围有关,因为以下代码无需static 关键字即可工作:
/**
* Simple LIFO stack implemented using linked lists
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct LinkedList LinkedList;
struct LinkedList{
int value;
LinkedList *next;
};
int pop(LinkedList **list){
LinkedList *next;
int ret;
ret = (*list)->value;
next = (*list)->next;
//free(*list);
*list = next;
return ret;
}
void push(LinkedList **list, int value){
LinkedList *new = (LinkedList*)malloc(sizeof(LinkedList));
new->value = value;
new->next = (*list);
*list = new;
}
int main() {
LinkedList *myList;
push(&myList, 0);
push(&myList, 1);
push(&myList, 2);
push(&myList, 3);
push(&myList, 4);
push(&myList, 5);
push(&myList, 6);
push(&myList, 7);
push(&myList, 8);
push(&myList, 9);
while(myList!=NULL)
printf("popped %i\n", pop(&myList));
return 0;
}
我知道分段错误的原因是 pop() 函数试图取消引用错误地址(因为显然 myList!=NULL 检查不起作用),但由于某种原因 static 关键字神奇解决所有问题!
唯一想到的另一件事是,它与将 for 循环中的 myList 指针的引用传递给 push() 有关。虽然不知道这是怎么回事……
谢谢!
【问题讨论】:
-
'new' 是 C++ 中的关键字。当使用可以编译 C++ 程序的编译器时,这将是一个问题。建议将“新”改为更有意义的东西
-
在 C 中调用 malloc()(和相关的函数族)时,1) 不强制转换返回值。它已经是一个 void * 因此可以分配给任何其他指针。 2) 始终检查 (!=NULL) 返回值以确保操作成功
-
在 pop() 函数中,一旦头指针越过第一个结构实例,指向该结构的指针仅在该函数中是已知的。因此,必须在该函数内执行对“断开连接”结构实例的 free() 的调用。发布的代码有必要的声明注释。如果不调用 free(),就会发生内存泄漏
-
在函数中:main() 指针'myList'需要初始化为NULL。因为 myList->next 在第一次调用 push() 时没有设置为 NULL,而是设置为 myList 第一次放入堆栈时 myList 中的垃圾。所以循环遍历链表不会看到终止的 NULL。
标签: c pointers static coredump