我是一名学生,并且得到了我已经从事了一周的课程。每当我运行该程序时,我都会遇到分段错误问题,我更改并尝试了几乎所有内容,在互联网上阅读了很多,没有任何帮助。我一直在尝试使用调试器来解决这个问题!
我认为这是我在<div class="header">
<h1>Step 1: Confucius</h1>
<p>He who copies the master, honours him</p>
</div>
<div class="parent">
<div class="topnav">
<button class="dropbtn">Professional</button>
<div class="dropdown-content">
<a href="first.php">Professional</a>
</div>
</div>
<div class="topnav">
<button class="dropbtn">Hobbies</button>
<div class="dropdown-content">
<a href="second.php">Test</a>
</div>
</div>
<div class="topnav">
<button class="dropbtn">Tutorials</button>
<div class="dropdown-content">
<a href="third.php">Test3</a>
</div>
</div>
</div>
中分配内存的方式,但是我对其进行了多次更改,没有任何效果...
这是我的程序:
eurovisionAddState()
答案 0 :(得分:4)
我一直在尝试使用调试器来解决这个问题!
调试器是诊断这种情况的重要工具,但是您仍然必须认真考虑代码的工作方式,以便了解调试器的内容。要记住的一个有用想法是,每次崩溃都是由某些特定的指令引起的, * ,而您的工作是找到该指令,然后弄清楚如何到达那里。
我每次运行该程序时都会遇到分段错误问题
好,那么什么指令导致分段错误?您的调试器应该能够将您指向该行。我的问题出在这里:
while (cn->before)
它还告诉我我们如何达到目标以及问题所在:
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
* frame #0: 0x000000010000064c DeleteThis`countryGetFirst(cn=0x8b480850ff078b48) at main.c:65
frame #1: 0x0000000100000688 DeleteThis`countryNodeExists(c=0x0000000102905f60, ID=1) at main.c:74
frame #2: 0x0000000100000a1e DeleteThis`eurovisionAddState(eurovision=0x0000000102908750, stateId=1, stateName="malta", songName="chameleon") at main.c:182
frame #3: 0x0000000100000b76 DeleteThis`main at main.c:212
frame #4: 0x00007fff617253d5 libdyld.dylib`start + 1
frame #5: 0x00007fff617253d5 libdyld.dylib`start + 1
(“ DeleteThis”只是我为该项目指定的名称-提醒我,我不需要在接下来的20分钟内保存它。此外,我删除了一些多余的空行,因此我的行数字可能与您不匹配。)
这里重要的是我们正在查看堆栈,我们可以看到countryGetFirst
由countryNodeExists
调用,而eurovisionAddState
又由main
调用了,从main
调用。好的,接下来我们需要知道问题线路为何崩溃。分段错误通常意味着您正在尝试取消引用错误的指针。确实,崩溃的行确实取消了某些指针的引用,但这不好吗?让我们找出它的来源...
您的eurovision
函数首先会像这样设置变量Eurovision eurovision = setupEurovision();
:
setupEurovision
那么eurovision->Countries
的作用是什么?它只是为Eurovision结构分配了一些空间,然后分配了另一个块并使Eurovision euro=(Eurovision)malloc(sizeof(*euro));
euro->Countries=(CountryNode)malloc(sizeof(struct CountryNode_t));
return euro;
指向它:
eurovisionAddState(eurovision, 1, "malta", "chameleon");
到目前为止看起来还好吧?接下来,那件事怎么办?好,接下来您添加一个国家:
eurovisionAddState
为此,if(countryNodeExists(eurovision->Countries,stateId))
致电:
eurovisionAddState
这很有趣,因为发生崩溃时,countryNodeExists
和eurovision->Countries
都在调用堆栈中,并且您 just 分配了countryNodeExists
,所以如果发生我们看CountryNode cn = countryGetFirst(c);
?好吧,它要做的第一件事就是调用崩溃的函数:
c
,它在此处传递的eurovision->Countries
就是呼叫者中的countryGetFirst
。嗯...继续前进。 while (cn->before)
中有什么?
cn
嗯。为什么会崩溃?这里的c
在呼叫者中称为eurovision->Countries
,在前一个呼叫者中是cn
,因此我们可以将eurovision->Countries
一直追溯到main
来自(CountryNode)malloc(sizeof(struct CountryNode_t));
。您认为那里有什么?记住,您是这样创建的:
malloc
(此外:您真的不应该转换malloc
的结果。在SO上搜索以找出原因。)
因此,您是使用cn = cn->before;
创建的。它有什么价值?您实际上并不知道该块中的内容,您只知道该块的地址,并且尚未在该地址保存任何内容。因此,有两种可能:它要么为零,要么为非零。非零的赔率非常好,那么接下来会发生什么呢?好吧,您执行循环的主体,因此您可以这样做:
before
好,因此此CountryNode
的{{1}}成员中的任何内容现在都在cn
中。同样,我们不知道该块中的内容,但是可以肯定地假设此before
值不是指向另一个CountryNode
的指针,因为您尚未在其中保存任何内容。因此,cn
现在是一些随机值。您到达了循环的结尾,由于是循环,所以重复:
while (cn->before)
嗯...现在您在cn
中取消引用该随机值,这时出现段错误,因为不允许从任何地方读取内存。
现在,我已经引导您完成了整个过程,以说明思考过程。但是,即使您不立即了解问题,您也应该能够使用调试器执行相同的操作……您始终可以在您知道问题发生之前的某个时刻设置断点,然后逐步执行一次说明一次,直到您遇到错误。您现在应该这样做,以帮助您自己真正地了解和理解该问题。完成后,我确定您将能够找到解决方法。
祝你好运!
* 为此概念而向Scott Knaster致信。How to Write Macintosh Software: The Debugging Reference for the Macintosh。
答案 1 :(得分:2)
为了在C中进行更安全的编程,这里有一些要做和不要的事情:
#define NOT_FOUND (-1)
int
成员就足够时,struct country_t { int ID; ...
malloc()
的返回值countryGetFirst
,cn == NULL
将崩溃(这是您的崩溃错误) eurovision->Countries
指向列表开头的指针即可。*(name + i)
:name[i]
strdup()
分配字符串副本,如果系统上不可用,则重写它:state->SongName = strdup(songName);
,
和;
以及if
,for
,while
关键字之后,在二进制运算符周围使用空格,在{
等之前gcc -Wall -Wextra
...