我很长时间没有触及过C.我的第一语言是C.但后来我们学习了C ++,Java和C#(在大学期间)。现在我的工作主要涉及Java和groovy。突然间我又要做C了。我不熟悉行业如何使用C,因为我从来没有在项目中使用C语言。
我开始使用eclipse CDT,在Windows 10上使用MinGW。我的新程序迅速发展壮大。我缺乏经验。当我运行时,我的程序曾经崩溃,显示Windows对话框“MyProgram.exe已停止工作”。现在我不知道什么是错的。编译很干净,没有错误,但只有一个警告。现在从Java世界开始,我就像警告一样并不致命。所以我只是忽略它(我认为我缺乏C经验)。并继续调试找到了原因。意识到警告确实是关于原因的。因调试浪费时间而感到精神沮丧。
所以这是我原始代码中的代码复制问题:
1 #include "stdio.h"
2 #include "limits.h"
3
4 typedef struct TempStruct TempStruct;
5
6 struct TempStruct
7 {
8 int a;
9 TempStruct *next;
10 };
11
12 int function1(TempStruct *param)
13 {
14 return param == NULL;
15 }
16
17 int function2(TempStruct **param)
18 {
19 if(function1(param))
20 {
21 return INT_MIN;
22 }
23 *param = (*param)->next;
24 return 0;
25 }
26
27 int main()
28 {
29 TempStruct *tempStructObj = NULL;
30 function2(&tempStructObj);
31 printf("Does not reach here!!!");
32 return 0;
33 }
我的C-noob眼睛没有看到任何错误。很好,我知道如何进行调试。我在调试中得到了以下信息:
在main()
中完成此操作:*tempStructObj = NULL
。所以,我希望function1()
返回1,使function2()
从第21行返回。
问题是function1()
需要TempStruct*
。但在第19行,我通过了它**param
。所以在function1()
内,param
不是NULL
。所以它返回false
(我猜是0
)。所以function2()
没有从第21行返回。它执行了(*param)->next
,因此程序崩溃了。
我的问题:
Error: Multiple errors reported...
是什么。偶尔会发生这种情况,但并非总是如此,在5次调试会话中说一次。这种临时行为背后的原因是什么? Q5。在上图中的第3点,0x62ff2c
内param
的{{1}}值是多少?如果我将function1()
的签名正确保留为function1()
并将内部引用正确更改为int function1(TempStruct **param)
,则*param
正确*param
(即0x0
):
修改
答案 0 :(得分:3)
Q1。不,他们是警告,因为他们是合法的C代码。 可能可能你想要这样的代码。您可以在gcc上使用-Werror
来发出错误警告。还要添加一些其他标志以打开更多警告,例如-Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare
等。这将更接近您在使用Java时可能习惯的内容; - )
Q2。至少在Linux上你有coredumps,iirc Windows是minidumps。这些可以与相应的可执行文件一起加载到调试器中。然后你可以访问回溯,值等。
Q3。
像上面一样,我问过设置让eclipse报告这个问题是致命的,或者让崩溃产生报告,这样可以快速修复东西,而不是长时间的调试。
记录自己。也可以使用宏来缓解这种情况。
你是否使用更好的(并且可能涉及更小的学习曲线)替代(eclipse CDT + MinGW + Windows),这将提供更强大的调试,以便我可以避免这样的错误。
IDE与C imho无关。使用Linux与本机GCC相反,MinGW很不错但它可能令人生畏(我的经验)。 当然MS VSC ++也可以编译C,但它只适用于C ++兼容,因此并不特定于一个标准。
Q4。好吧,列出了多个错误。如果它很难重现它可能是你的设置中的一个问题,这正是我在Windows上使用MinGW的经验。
Q5。它是地址 - 你有一个指向指针的指针,所以第一个(“外部”)指针就是那个地址,指向另一个指针NULL
。
或者更详细地说:
tempStructObj
是指向NULL
的指针(即int_ptr
,其中包含值0x0
。
要function2
向int_ptr
传递保存自动变量int_ptr tempStructObj
的半随机值/地址的另一个&tempStructObj
IE浏览器。你有这样的:
地址tempStructObj
:function1
。
然后在调用NULL
时,传递this(不是 - *param
)指针的值。当然,比较总是错误的。
你需要比较一下
NULL
与gcc -std=c99 -Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare -o main main.c
main.c: In function ‘function2’:
main.c:19:18: warning: passing argument 1 of ‘function1’ from incompatible pointer type [-Wincompatible-pointer-types]
if(function1(param))
^
main.c:12:5: note: expected ‘TempStruct * {aka struct TempStruct *}’ but argument is of type ‘TempStruct ** {aka struct TempStruct **}’
int function1(TempStruct *param)
^
。
更多: 如果您使用GCC进行编译(在Linux上)并使用非常详细的标志,您将获得:
function1
确切地说你遇到的问题是^^
此外,我完全删除了struct
,这完全没必要,只是模糊了代码。另外,我会为typedef
和_t
使用不同的名称,后者附加\n
。我还将它移到一段较短的代码中。
在旁注中:在printf()
- 呼叫中添加#include <stdio.h>
#include <limits.h>
typedef struct TempStruct_s {
int a;
struct TempStruct_s *next;
} TempStruct_t;
int function(TempStruct_t **param)
{
if(!*param) {
return INT_MIN;
}
*param = (*param)->next;
return 0;
}
int main()
{
TempStruct_t *tempStructObj = NULL;
function(&tempStructObj);
printf("Does not reach here!!!\n");
return 0;
}
。
编辑代码:
<html>
<body>
<script>
$(document).ready(function() {
$.ajax({
url: "Search.html",
type: "POST",
dataType : "json",
success: function (result) {
console.log(result);
if(result.status == 200 && result.validationFailed ){
alert(result.message);
}
},
error: function(result){
console.log(result);
if(error.responseText == 'showAlert'){
alert( "Sorry, there was a problem!" );
}
}
})
});
}
</script>
<form action="/process_post" method="POST">
<select name="SearchTypes">
<option value="Author" selected>Author</option>
<option value="Mention">Mention</option>
<option value="Tag">Tag</option>
</select>
<input type="text" name="term">
<br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
答案 1 :(得分:0)
当你
TempStruct *tempStructObj = NULL;
function2(&tempStructObj);
您要将变量function2
(0x62ff2c)的地址发送到tempStructObj
。做的时候
if(function1(param)){
return INT_MIN;
}
您正在发送相同的地址(0x62ff2c)。因此,param == NULL
为false
。
问题5:如果你按照建议使用正确的签名,那么你检查tempStructObj
指向的值,这是你想要的,一切正常。
您无法访问内存0x4的错误是由于您的结构和错误的空检查。 (*param)->next
预计会在具有int
和另一个指针的内存区域上工作。但是,*param
指向地址0x0,因此int位于地址0x0,next
指针位于地址0x4,因此出错。