为什么这个分段错误在各个版本中不一致?
我写了一个ac程序,编译了它,运行得很好。经过几次编译后 - 它开始给我一个分段错误。我重命名了该文件夹,重新编译,它再次工作。
这是正常现象吗?出现不一致的分段错误?我更改输出名称,更改文件夹名称等......并且它从给出分段错误跳到不给出分段错误。我不知道该怎么办了。
我的意思是,如果是编码问题,seg failure应该是一致的,对吧?我每次都应该得到它。这是代码:
file my_set.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
/*
The program acceps a set of numbers from stdin until EOF
And then prints them (not storing duplicate numbers)
*/
int main ()
{
int num;
nodePtr head; /*head of the list*/
while (scanf("%d", &num) != EOF)
{
addToList(num, &head);
}
printList(head);
freeList(head);
return 0;
}
file list.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
/*
Implements a linked list, each element of which contains a dynamic array.
I used a linked list to maximize potential memory in case it is fragmented.
I use a dynamic array in each node to minimize the percentage of overhead
from creating a list (the pointer, the index...);
*/
/*
Adds number n to list *h
4 cases:
1. list is empty:
creating one
updating h with new list
creating a new dynamic array in the list
updating it and the index
2. can reallocate current node's array for 1 more int
3. cannot reallocate current node's array:
creating a new node
initializing it
4. cannot create a new node
printing the current list, an "out of memory error" and freeing all memory.
*/
void addToList(int n, nodePtr *h)
{
static nodePtr p; /*points to current last node*/
int *temp; /*for use in reallocation*/
if (!*h) /*first item of set*/
{
*h = malloc (sizeof(node));
(*h)->arr = malloc(sizeof(int));
(*h)->arr[0] = n;
(*h)->i = 1;
p = *h;
return;
}
/*if n is already in the list, no need to add it
the call comes after first item, because first item cannot be in the list*/
if(existsInList(n, *h)) return;
/*using realloc while still possible*/
if ((temp = realloc(p->arr, (p->i+1)*sizeof(int))))
{
p->arr = temp;
p->arr[p->i] = n;
p->i++;
return;
}
/*if realloc no longet possible - start new node*/
if ((p->next = malloc(sizeof(node))))
{
p = p->next;
p->arr = malloc(sizeof(int));
p->arr[0] = n;
p->i = 1;
return;
}
/*can no longer start new nodes - quit with error, after printing*/
printf("out of memory!");
printList(*h);
freeList(*h);
}
/*checks if n is in p assuming p is not null
it can asume so because the call for it comes after the check for first item*/
int existsInList(int n, nodePtr p)
{
int i;
for (; p ; p = p->next)
for (i = 0; i < p->i; i++)
if (p->arr[i] == n)
return 1;
return 0;
}
/*frees the list*/
void freeList(nodePtr p)
{
nodePtr temp = p;
if (!p) return; /*list is empty*/
while (p)
{
free(p->arr);
p = p->next;
free(temp);
}
}
/*prints the content of the list to stdout*/
void printList(nodePtr p)
{
if (!p) return;
int i;
printf("\n");
for (; p ; p = p->next)
for (i = 0; i < p->i; i++)
printf("%d ", p->arr[i]);
printf("\n");
}
file list.h:
/*
pointer to a node
declare a variable of this type to create a list
then start adding to the list
*/
typedef struct s *nodePtr;
/*the struct that represents each node of the list
reason for dynamic array is in "list.c"
*/
typedef struct s
{
int *arr;
int i; /*index for next num, also size of array;*/
nodePtr next;
}node;
/*Adds the int to list at nodePtr omitting duplicates*/
void addToList(int, nodePtr*);
/*prints a list*/
void printList(nodePtr);
/*returns 1 if an int exists in list referenced by nodePtr, 0 otherwise*/
int existsInList(int, nodePtr);
/*frees all dynamically allocated memory*/
void freeList(nodePtr);
基本上我所做的就是从标准输入获取数字,将它们放入列表中(没有重复项),然后打印它们。我使用动态数组列表。
I wrote a c program, compiled it and it ran fine. After a few compiles - it started giving me a segmentation fault. I renamed the folder, recompiled and it worked again.
Is this something normal? To have an inconsistent segmentation fault? I change the output name, change folder names etc.. and it bounces from giving segmentation fault to not giving seg fault. I don't know what to do anymore.
I mean, if it is a coding problem, seg fault should be consistent, right? I should get it every time. here's the code:
file my_set.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
/*
The program acceps a set of numbers from stdin until EOF
And then prints them (not storing duplicate numbers)
*/
int main ()
{
int num;
nodePtr head; /*head of the list*/
while (scanf("%d", &num) != EOF)
{
addToList(num, &head);
}
printList(head);
freeList(head);
return 0;
}
file list.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
/*
Implements a linked list, each element of which contains a dynamic array.
I used a linked list to maximize potential memory in case it is fragmented.
I use a dynamic array in each node to minimize the percentage of overhead
from creating a list (the pointer, the index...);
*/
/*
Adds number n to list *h
4 cases:
1. list is empty:
creating one
updating h with new list
creating a new dynamic array in the list
updating it and the index
2. can reallocate current node's array for 1 more int
3. cannot reallocate current node's array:
creating a new node
initializing it
4. cannot create a new node
printing the current list, an "out of memory error" and freeing all memory.
*/
void addToList(int n, nodePtr *h)
{
static nodePtr p; /*points to current last node*/
int *temp; /*for use in reallocation*/
if (!*h) /*first item of set*/
{
*h = malloc (sizeof(node));
(*h)->arr = malloc(sizeof(int));
(*h)->arr[0] = n;
(*h)->i = 1;
p = *h;
return;
}
/*if n is already in the list, no need to add it
the call comes after first item, because first item cannot be in the list*/
if(existsInList(n, *h)) return;
/*using realloc while still possible*/
if ((temp = realloc(p->arr, (p->i+1)*sizeof(int))))
{
p->arr = temp;
p->arr[p->i] = n;
p->i++;
return;
}
/*if realloc no longet possible - start new node*/
if ((p->next = malloc(sizeof(node))))
{
p = p->next;
p->arr = malloc(sizeof(int));
p->arr[0] = n;
p->i = 1;
return;
}
/*can no longer start new nodes - quit with error, after printing*/
printf("out of memory!");
printList(*h);
freeList(*h);
}
/*checks if n is in p assuming p is not null
it can asume so because the call for it comes after the check for first item*/
int existsInList(int n, nodePtr p)
{
int i;
for (; p ; p = p->next)
for (i = 0; i < p->i; i++)
if (p->arr[i] == n)
return 1;
return 0;
}
/*frees the list*/
void freeList(nodePtr p)
{
nodePtr temp = p;
if (!p) return; /*list is empty*/
while (p)
{
free(p->arr);
p = p->next;
free(temp);
}
}
/*prints the content of the list to stdout*/
void printList(nodePtr p)
{
if (!p) return;
int i;
printf("\n");
for (; p ; p = p->next)
for (i = 0; i < p->i; i++)
printf("%d ", p->arr[i]);
printf("\n");
}
file list.h:
/*
pointer to a node
declare a variable of this type to create a list
then start adding to the list
*/
typedef struct s *nodePtr;
/*the struct that represents each node of the list
reason for dynamic array is in "list.c"
*/
typedef struct s
{
int *arr;
int i; /*index for next num, also size of array;*/
nodePtr next;
}node;
/*Adds the int to list at nodePtr omitting duplicates*/
void addToList(int, nodePtr*);
/*prints a list*/
void printList(nodePtr);
/*returns 1 if an int exists in list referenced by nodePtr, 0 otherwise*/
int existsInList(int, nodePtr);
/*frees all dynamically allocated memory*/
void freeList(nodePtr);
Basically all I do is get numbers from stdin, put them in a list(no duplicates) and then print them. I use a list of dynamic arrays.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
初始化你的变量!
添加:不一致的行为可能来自调试与发布编译,通常调试模式下的编译器将未初始化的变量设置为奇怪的值,例如 0xDDDDDDDD 以使问题立即可见。在释放模式下,如果内存块被清零,将会发生变量内容为0的情况,但不能保证这一点。
Initialize your variables!
ADD: The inconsistent behaviour can come from debug vs release compilation, usually compilers in debug mode set the non-initialized variables to weird values like
0xDDDDDDDD
to make the problem immediately visible. In release mode if the memory block is zeroed it will happen that the content of the variables is 0 but there is no guarantee for it.您应该检查
malloc()
的返回值,以防它返回NULL
(内存不足)。You should check the returns values from
malloc()
in case it's returningNULL
(out of memory).C/C++ 程序中的间歇性段错误通常是由未初始化的内存引起的,通常是在指针变量中。
您发布了很多代码,这使得仅仅阅读它们就很难进行调试。我建议仔细检查代码,并在声明变量的任何位置为其指定一个初始值(例如零或 NULL)。请记住,编译器不会为您初始化它们。
您可能应该首先在
main()
中初始化num
和head
的值。例如EDIT 1
另一个错误是在
addToList()
中。如果该函数中的第一个if
块未执行,则当您稍后调用realloc(p->arr 时,局部变量
。当您取消引用p
的值将未初始化,...)p
来获取p->arr 时,如果
p` 未初始化,那么您通常会遇到段错误。编辑 2
在 C/C++ 中编程时的两个有用技巧:
所以,不要:
尝试类似的事情:
Intermittent segfaults in c/c++ programs are usually caused by uninitialised memory, often in pointer variables.
You've posted a lot of code, which makes it hard to debug just be reading it. I suggest going through the code and, wherever a variable is declared, giving it an initial value (e.g. zero or NULL). Remember that the compiler will not initialise them for you.
You should probably start by initialising the values of
num
andhead
inmain()
. E.g.EDIT 1
Another bug is in
addToList()
. If the firstif
block in that function is not executed then the value of the local variablep
will be uninitailised when you later callrealloc(p->arr, ...)
. When you dereferencep
to getp->arr, if
p` is uninitialised then you will usually get a segfault.EDIT 2
Two useful techniques when programming in C/C++ :
So, instead of:
try something like: